diff --git a/design_hashset.py b/design_hashset.py new file mode 100644 index 00000000..f3173289 --- /dev/null +++ b/design_hashset.py @@ -0,0 +1,41 @@ +# Time Complexity : O(1)* - * could be O(n) if all n inserted values happen to fall in the same bucket, thus requiring us to scan through the entire array n-times +# Space Complexity : O(n) - for n elements being added +# Did this code successfully run on Leetcode : yes +# Any problem you faced while coding this : no + + +# Your code here along with comments explaining your approach +# we initiated an array of empty arrays so we can add new values to them by using % bucket_size. in each bucket, we add/remove the same way we would a normal array. + + +class MyHashSet: + + # Time: O(1) + # Space: O(1) + def __init__(self): + self.bucket_size = 1000001 + self.buckets = [[] for _ in range(self.bucket_size)] + + # Time: O(1)* + # Space: O(1) + def add(self, key: int) -> None: + if key not in self.buckets[key % self.bucket_size]: + self.buckets[key % self.bucket_size].append(key) + + # Time: O(1)* + # Space: O(1) + def remove(self, key: int) -> None: + if key in self.buckets[key % self.bucket_size]: + self.buckets[key % self.bucket_size].remove(key) + + # Time: O(1)* + # Space: O(1) + def contains(self, key: int) -> bool: + return key in self.buckets[key % self.bucket_size] + + +# Your MyHashSet object will be instantiated and called as such: +# obj = MyHashSet() +# obj.add(key) +# obj.remove(key) +# param_3 = obj.contains(key) diff --git a/design_minstack.py b/design_minstack.py new file mode 100644 index 00000000..faba5a1a --- /dev/null +++ b/design_minstack.py @@ -0,0 +1,47 @@ +# Time Complexity : O(1) +# Space Complexity : O(n) +# Did this code successfully run on Leetcode : yes +# Any problem you faced while coding this : no, only understanding the concept but once i understood it, coding was straightforward + + +# Your code here along with comments explaining your approach +# It look me a little bit to understand minstack but I came to the conclusion that two lists are needed for it: one to keep track of a normal stack, and one to keep track of the minimum value for constant time retrieval. Once I understood that, the rest of the functions was pretty self explanatory and straighforward + + +class MinStack: + + def __init__(self): + self.stack = [] + self.minStack = [] + + # Time: O(1) + # Space: O(1) + def push(self, val: int) -> None: + self.stack.append(val) + if len(self.minStack) == 0 or val <= self.minStack[-1]: + self.minStack.append(val) + + # Time: O(1) + # Space: O(1) + def pop(self) -> None: + val = self.stack.pop() + if val == self.minStack[-1]: + self.minStack.pop() + + # Time: O(1) + # Space: O(1) + def top(self) -> int: + return self.stack[-1] + + # Time: O(1) + # Space: O(1) + def getMin(self) -> int: + return self.minStack[-1] + + +# Your MinStack object will be instantiated and called as such: +# obj = MinStack() +# obj.push(val) +# obj.pop() +# param_3 = obj.top() +# param_4 = obj.getMin()