From c8399fad96bfa2c9317f922dfac9ecab1aed14a1 Mon Sep 17 00:00:00 2001 From: yolophg Date: Sat, 15 Mar 2025 03:02:39 -0400 Subject: [PATCH 1/5] solve: countingBits --- counting-bits/yolophg.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 counting-bits/yolophg.py diff --git a/counting-bits/yolophg.py b/counting-bits/yolophg.py new file mode 100644 index 000000000..0e5e74345 --- /dev/null +++ b/counting-bits/yolophg.py @@ -0,0 +1,18 @@ +# Time Complexity: O(n) -> iterate from 1 to n, updating arr[] in O(1) for each i. +# Space Complexity: O(n) -> store results in an array of size (n+1). + +class Solution: + def countBits(self, n: int) -> List[int]: + # make an array of size (n+1), initialized with 0s. + arr = [0] * (n + 1) + + # loop from 1 to n + for i in range(1, n + 1): + if i % 2 == 0: + # even number -> same count as i//2 + arr[i] = arr[i // 2] + else: + # odd number -> one more bit than i//2 + arr[i] = arr[i // 2] + 1 + + return arr From b2848261bcdfec596b21dbfcba9cc77be9a7c896 Mon Sep 17 00:00:00 2001 From: yolophg Date: Sat, 15 Mar 2025 03:07:10 -0400 Subject: [PATCH 2/5] solve: binaryTreeLevelOrderTraversal --- binary-tree-level-order-traversal/yolophg.py | 36 ++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 binary-tree-level-order-traversal/yolophg.py diff --git a/binary-tree-level-order-traversal/yolophg.py b/binary-tree-level-order-traversal/yolophg.py new file mode 100644 index 000000000..159f9ded0 --- /dev/null +++ b/binary-tree-level-order-traversal/yolophg.py @@ -0,0 +1,36 @@ +# Time Complexity: O(n) -> visit each node exactly once. +# Space Complexity: O(n) -> in the worst case, the queue holds all nodes at the last level. + +class Solution: + def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + + # list to store level order traversal. + ans = [] + + # if the tree is empty, return an empty list. + if root is None: + return ans + + # queue to process nodes level by level. + q = deque([root]) + + while q: + # list to store values of nodes at the current level. + t = [] + + # process all nodes at this level. + for _ in range(len(q)): + # pop the first node from the queue. + node = q.popleft() + # add node's value to the list. + t.append(node.val) + + if node.left: + q.append(node.left) + if node.right: + q.append(node.right) + + # add current level values to the result list. + ans.append(t) + + return ans From 5f08c01b5d91dbc2d93555c1749de8f682489118 Mon Sep 17 00:00:00 2001 From: yolophg Date: Sat, 15 Mar 2025 03:11:10 -0400 Subject: [PATCH 3/5] solve: houseRobberIi --- house-robber-ii/yolophg.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 house-robber-ii/yolophg.py diff --git a/house-robber-ii/yolophg.py b/house-robber-ii/yolophg.py new file mode 100644 index 000000000..ad80b56de --- /dev/null +++ b/house-robber-ii/yolophg.py @@ -0,0 +1,32 @@ +# Time Complexity: O(n) -> iterate through the houses twice, each in O(n) time. +# Space Complexity: O(1) -> use a few extra variables, no additional data structures. + +class Solution: + def rob(self, nums: List[int]) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + + # track the max money from two houses before and last house. + var1, var2 = 0, 0 + + # robbing from first house to second-last house (excluding last house) + for i in nums[:-1]: + # store previous max before updating. + temp = var1 + # either rob this house or skip it. + var1 = max(var2 + i, var1) + # move to the next house. + var2 = temp + + # same logic, but robbing from second house to last house. + vaar1, vaar2 = 0, 0 + + for i in nums[1:]: + temp = vaar1 + vaar1 = max(vaar2 + i, vaar1) + vaar2 = temp + + # take the max of both cases. + return max(var1, vaar1) From c8d1ff907b080eadc8b81941541efcf1f92fa3ba Mon Sep 17 00:00:00 2001 From: yolophg Date: Sat, 15 Mar 2025 03:14:31 -0400 Subject: [PATCH 4/5] solve: meetingRoomsIi --- meeting-rooms-ii/yolophg.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 meeting-rooms-ii/yolophg.py diff --git a/meeting-rooms-ii/yolophg.py b/meeting-rooms-ii/yolophg.py new file mode 100644 index 000000000..b78f62fca --- /dev/null +++ b/meeting-rooms-ii/yolophg.py @@ -0,0 +1,22 @@ + # Time Complexity: O(n log n) -> sorting takes O(n log n), and heap operations take O(log n) per interval. + # Space Complexity: O(n) -> in the worst case, store all meetings in the heap. + +class Solution: + def minMeetingRooms(self, intervals: List[List[int]]) -> int: + if not intervals: + return 0 + + # sort meetings by start time. + intervals.sort() + + # heap to keep track of meeting end times. + min_heap = [] + + for start, end in intervals: + if min_heap and min_heap[0] <= start: + # remove the meeting that has ended. + heapq.heappop(min_heap) + # add the current meeting's end time. + heapq.heappush(min_heap, end) + + return len(min_heap) From 0cc1d2925089a586e9c7fbc2989aa9cbb0f2a060 Mon Sep 17 00:00:00 2001 From: yolophg Date: Sat, 15 Mar 2025 03:26:41 -0400 Subject: [PATCH 5/5] solve: wordSearchIi --- word-search-ii/yolophg.py | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 word-search-ii/yolophg.py diff --git a/word-search-ii/yolophg.py b/word-search-ii/yolophg.py new file mode 100644 index 000000000..5a7cc8806 --- /dev/null +++ b/word-search-ii/yolophg.py @@ -0,0 +1,45 @@ +# Time Complexity: O(m * n * 4^l) -> each cell can explore up to 4 directions recursively, where l is the max word length. +# Space Complexity: O(w * l) -> storing words in a dictionary-based Trie. + +class Solution: + def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: + # trie-like dictionary to store words + d = {} + + # build the trie + for word in words: + cur = d + for c in word: + if c not in cur: + # create a new node + cur[c] = {} + cur = cur[c] + # mark the end of the word + cur["*"] = word + + # right, down, up, left + directions = [(0, 1), (1, 0), (-1, 0), (0, -1)] + + # backtracking function + def dfs(i, j, cur, seen): + result = set() + if "*" in cur: + # found a word, add it + result = {cur["*"]} + + for x, y in directions: + ni, nj = i + x, j + y + if 0 <= ni < len(board) and 0 <= nj < len(board[0]) and (ni, nj) not in seen and board[ni][nj] in cur: + result.update(dfs(ni, nj, cur[board[ni][nj]], seen | {(ni, nj)})) + + return result + + result = set() + + # start dfs search from every cell in the board + for i in range(len(board)): + for j in range(len(board[0])): + if board[i][j] in d: + result.update(dfs(i, j, d[board[i][j]], {(i, j)})) + + return list(result)