Skip to content

Commit 0ca4e18

Browse files
[dolphinflow86] WEEK 04 Solutions (#2741)
* merge two sorted lists solution * maximum depth of binary tree solution * find minimum in rotated sorted array solution * word search solution * Update maximum-depth-of-binary-tree/dolphinflow86.py 오 넵 이게 낫겠네요! 변수를 쓴다면 더 명시적으로 적어보겠습니다. Co-authored-by: Hojeong Park <parkhj062@gmail.com> * apply code review * coin change solution --------- Co-authored-by: Hojeong Park <parkhj062@gmail.com>
1 parent c2bba21 commit 0ca4e18

5 files changed

Lines changed: 129 additions & 0 deletions

File tree

coin-change/dolphinflow86.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# 1) Use top-down memoization, recursively calculate the minimum coins required for each remaining amount and cache the results to prune duplicated branches.
2+
# TC: O(K^M) where K is the number of coins, where M is the amount. We can recurse down at most M depth
3+
# SC: O(K + M)
4+
class Solution:
5+
def dfs(self, coins: List[int], memo:Dict[int, int], remain: int):
6+
if remain == 0: return 0
7+
if remain < 0: return float('inf')
8+
if remain in memo: return memo[remain]
9+
10+
min_result = float('inf')
11+
for coin in coins:
12+
min_result = min(min_result, self.dfs(coins, memo, remain - coin))
13+
14+
memo[remain] = min_result if min_result == float('inf') else min_result + 1
15+
return memo[remain]
16+
17+
def coinChange(self, coins: List[int], amount: int) -> int:
18+
result = self.dfs(coins, {}, amount)
19+
return result if result != float('inf') else -1
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# 1) Use binary search to halves to search range. Each iteration,
2+
# compare with nums[pivot] and nums[right] to see which side has a smaller range.
3+
# Firstly I compare nums[left] with nums[right] so I got the wrong results but end up with the right solution.
4+
# TC: O(logN) where N is the length of the nums array
5+
# SC: O(1)
6+
7+
class Solution:
8+
def findMin(self, nums: List[int]) -> int:
9+
n = len(nums)
10+
left = 0
11+
right = n-1
12+
13+
while left < right:
14+
mid = left + (right - left) // 2
15+
if nums[mid] < nums[right]:
16+
right = mid
17+
else:
18+
left = mid + 1
19+
20+
return nums[right]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# 1) Use DFS to traverse down to the leaf node. Keep track of depth and return each node's maximum depth of each subtree to the parent node.
2+
# TC: O(N) where N is the number of node in the binary tree
3+
# SC: O(H) where H is the height of the binary tree
4+
# Definition for a binary tree node.
5+
# class TreeNode:
6+
# def __init__(self, val=0, left=None, right=None):
7+
# self.val = val
8+
# self.left = left
9+
# self.right = right
10+
class Solution:
11+
def dfs(self, node: Optional[TreeNode], depth: int) -> int:
12+
if not node:
13+
return depth
14+
15+
return max(
16+
self.dfs(node.left, depth + 1),
17+
self.dfs(node.right, depth + 1)
18+
)
19+
20+
def maxDepth(self, root: Optional[TreeNode]) -> int:
21+
return self.dfs(root, 0)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# 1) Use a dummy node and connect the smaller node to the merged list while iterating through both lists.
2+
# TC: O(N + M) where N is the length of list1 and M is the length of list2.
3+
# SC: O(1)
4+
#
5+
# Definition for singly-linked list.
6+
# class ListNode:
7+
# def __init__(self, val=0, next=None):
8+
# self.val = val
9+
# self.next = next
10+
11+
class Solution:
12+
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
13+
dummy = ListNode()
14+
curr = dummy
15+
16+
while list1 and list2:
17+
if list1.val < list2.val:
18+
curr.next = list1
19+
list1 = list1.next
20+
else:
21+
curr.next = list2
22+
list2 = list2.next
23+
curr = curr.next
24+
25+
curr.next = list1 if list1 else list2
26+
27+
return dummy.next

word-search/dolphinflow86.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# 1) Use dfs and backtracking to search for a word in the board.
2+
# TC: O(N*M*3^W) where N is len(row), M is len(col) and W is len(word)
3+
# SC: O(N*M) representing the maximum depth of the recursion tack.
4+
class Solution:
5+
def dfs(self, board: List[List[str]], word: str, row: int, col: int, word_idx: int) -> bool:
6+
if row < 0 or col < 0 or row >= len(board) or col >= len(board[0]):
7+
return False
8+
9+
if word_idx >= len(word) or board[row][col] != word[word_idx]:
10+
return False
11+
12+
if word_idx == len(word) - 1:
13+
return True
14+
15+
temp = board[row][col]
16+
board[row][col] = '#'
17+
18+
found = (
19+
self.dfs(board, word, row + 1, col, word_idx + 1) or
20+
self.dfs(board, word, row - 1, col, word_idx + 1) or
21+
self.dfs(board, word, row, col + 1, word_idx + 1) or
22+
self.dfs(board, word, row, col - 1, word_idx + 1)
23+
)
24+
25+
board[row][col] = temp
26+
27+
return found
28+
29+
def exist(self, board: List[List[str]], word: str) -> bool:
30+
row_len = len(board)
31+
column_len = len(board[0])
32+
word_len = len(word)
33+
34+
# Early return if the board contains fewer cells than the word length.
35+
if row_len * column_len < word_len: return False
36+
37+
for i in range(row_len):
38+
for j in range(column_len):
39+
if self.dfs(board, word, i, j, 0):
40+
return True
41+
42+
return False

0 commit comments

Comments
 (0)