diff --git a/DesignHashSet.py b/DesignHashSet.py new file mode 100644 index 00000000..ee219319 --- /dev/null +++ b/DesignHashSet.py @@ -0,0 +1,28 @@ +# This approach uses an array of fixed size and maps each key to an index using a hash function (key % size). +# Each index stores a bucket to handle collisions using chaining. +# All operations: add, remove, contains—run in O(1) average time because each bucket stays small. + +class MyHashSet: + + def __init__(self): + self.size = 1000 + self.buckets = [[] for _ in range(self.size)] + + def _hash(self, key): + return key % self.size + + def add(self, key: int) -> None: + idx = self._hash(key) + bucket = self.buckets[idx] + if key not in bucket: + bucket.append(key) + + def remove(self, key: int) -> None: + idx = self._hash(key) + bucket = self.buckets[idx] + if key in bucket: + bucket.remove(key) + + def contains(self, key: int) -> bool: + idx = self._hash(key) + return key in self.buckets[idx] diff --git a/minStack.py b/minStack.py new file mode 100644 index 00000000..0320b8e1 --- /dev/null +++ b/minStack.py @@ -0,0 +1,28 @@ +# two stacks: one for all values and one for tracking the minimum at each level. +# Every time we push a value, we also push the new minimum so far onto the min stack. +# This ensures that getMin(), top(), and pop() all run in O(1) time with no extra computation. + +class MinStack: + + def __init__(self): + self.stack = [] # main stack + self.min_stack = [] # stack of minimums + + def push(self, val: int) -> None: + self.stack.append(val) + # If min_stack is empty or val is smaller/equal, push it as the new minimum + if not self.min_stack or val <= self.min_stack[-1]: + self.min_stack.append(val) + else: + # Repeat the current minimum to keep stacks aligned + self.min_stack.append(self.min_stack[-1]) + + def pop(self) -> None: + self.stack.pop() + self.min_stack.pop() + + def top(self) -> int: + return self.stack[-1] + + def getMin(self) -> int: + return self.min_stack[-1]