diff --git a/Problem 1.py b/Problem 1.py new file mode 100644 index 00000000..4dbc8f3f --- /dev/null +++ b/Problem 1.py @@ -0,0 +1,47 @@ +# Time Complexity : O(1) for all operations +# Space Complexity : O(1) fixed size +#Did this code successfully run on Leetcode : Yes +#Any problem you faced while coding this : Yes: went back and forth to understand add funtion + +# We create a storage list of 1000 slots, each slot starts as None and only builds an inner list of 1000 False values when a key needs it +# Every key maps to an exact position using key%1000 for outer slot and key//1000 for inner position +# At that position, add sets True, remove sets False, contains returns whatever is there + +class MyHashSet: + def __init__(self): + self.hash1= 1000 #initializing the size of hash1 & hash2 to 1000 + self.hash2 = 1000 + self.storage = [None] *1000 #initializing our storage with false + + def primary(self,key:int): + return key % self.hash1 #this is where we are deciding the index for the key in the storage array + + def secondary(self,key:int): + return key// self.hash2 #this is where we are deciding the index for the key in the secondary array + + def add(self, key: int) -> None: + index = self.primary(key) #the key is passed in the primary function to check where we need to store the key + if self.storage[index] is None: #if the index is empty the we will create a new array under the index of size 1000 + if index == 0: #we will have a special case for index 0 because the 1M key will not be stored if we do not increase the size of secondary array to 1001 + self.storage[index]= [False]*(self.hash2 +1) + else: + self.storage[index]= [False]*self.hash2 #for all the other keys,the size of secondary array will be 1000 only + index2= self.secondary(key) #if the primary array is not empty then we will pass the key to secondary array and find it a place to store + self.storage[index][index2]=True #mark the place as true where the key is stored + + def remove(self, key: int) -> None: + index = self.primary(key) #we again pass the key to primary function to find the index of the key in the storage array + if self.storage[index] is None: #if it doesn not exist then we just return None + return + index2 = self.secondary(key) #if the primary array is not empty then we will pass the key to secondary array and find it a place to remove and return false + self.storage[index][index2]=False + + + def contains(self, key: int) -> bool: + index = self.primary(key) #we again pass the key to primary function to find the index of the key in the storage array + if self.storage[index] is None: #if it does not exist then we just return false + return False + index2 = self.secondary(key) #if the primary array is not empty then we will pass the key to secondary array and find it a place to check if the key is present or not and return true or false accordingly + return self.storage[index][index2] + + \ No newline at end of file diff --git a/Problem2.py b/Problem2.py new file mode 100644 index 00000000..d1dcccc8 --- /dev/null +++ b/Problem2.py @@ -0,0 +1,43 @@ +# Time Complexity: O(1) for all operations: push, pop, top and getMin all use +# Space Complexity: O(n) both stacks grow by 1 on every push, giving us O(2n) which simplifies to O(n) + +# We maintain two stacks in parallel - the main stack stores all values while the min stack stores a snapshot of the current minimum at every level + +# On every push we compare the new value against the current min and update it, so we always know the minimum without ever having to search + +# Logic: On every pop we remove from both stacks simultaneously and the new minimum is automatically restored by looking at the top of the min stack + +class MinStack: + + def __init__(self): #here we are initializing 2 explty stacks + self.stack =[] #the first stack is the enter all the values + self.minstack=[] #the 2nd one is to maintain values that are min corresponding to the elements + self.min = float('inf') #we need t set the value in the minstack to infinity so whatever number next enters will automatically be the new min value + self.minstack.append(self.min) #we need to append infinity into min stack + + def push(self, value: int) -> None: + self.min = min(value,self.min) #it just returns the min value everytime + self.stack.append(value) # here we are appending the values to the main stack + self.minstack.append(self.min) #here we are appending the min values only + + def pop(self) -> None: + self.stack.pop() #we pop the element using pop funtion + self.minstack.pop() + self.min = self.minstack[-1] #we need to update the new min value and it will be the topmost value in the table + + + def top(self) -> int: + return self.stack[-1] + + + def getMin(self) -> int: + return self.min + + + +# Your MinStack object will be instantiated and called as such: +# obj = MinStack() +# obj.push(value) +# obj.pop() +# param_3 = obj.top() +# param_4 = obj.getMin() \ No newline at end of file