Skip to content

[Helena] Week 14 #1103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions binary-tree-level-order-traversal/yolophg.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yolophg 님 안녕하세요! 저도 이 문제를 BFS로 구현했습니다. DFS로 풀면 시간 효율성을 높일 수 있다는 리뷰를 받았는데, 헬레나님도 이 방법으로 풀어보시면 좋을 것 같습니다!

Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions counting-bits/yolophg.py
Original file line number Diff line number Diff line change
@@ -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
32 changes: 32 additions & 0 deletions house-robber-ii/yolophg.py
Original file line number Diff line number Diff line change
@@ -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)
22 changes: 22 additions & 0 deletions meeting-rooms-ii/yolophg.py
Original file line number Diff line number Diff line change
@@ -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)
45 changes: 45 additions & 0 deletions word-search-ii/yolophg.py
Original file line number Diff line number Diff line change
@@ -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)