Skip to content

Commit 4aee128

Browse files
authored
Merge pull request #1340 from hi-rachel/main
[hi-rachel] Week 04 Solutions
2 parents c6ddebb + 412bf7b commit 4aee128

File tree

9 files changed

+305
-0
lines changed

9 files changed

+305
-0
lines changed

coin-change/hi-rachel.py

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
# BFS -> 먼저 찾는 해답이 가장 적은 연산/가장 짧은 거리 -> 가장 적은 count부터 계산해 최소한의 동전 수 보장
3+
# O(amount * n) time, O(amount) space
4+
5+
from collections import deque
6+
7+
class Solution:
8+
def coinChange(self, coins: List[int], amount: int) -> int:
9+
queue = deque([(0, 0)]) # (동전 개수, 현재 금액)
10+
visited = set()
11+
while queue:
12+
count, total = queue.popleft()
13+
if total == amount:
14+
return count
15+
if total in visited:
16+
continue
17+
visited.add(total)
18+
for coin in coins:
19+
if total + coin <= amount:
20+
queue.append((count + 1, total + coin))
21+
return - 1
22+
23+
24+
# DP 풀이
25+
# 어떤 금액을 만드는데 필요한 동전 개수를 알면, 그 금액보다 큰 금액을 만드는데 필요한 동전 개수도 알 수 있다.
26+
# dp[i] = min(dp[i], dp[i - coin] + 1)
27+
# O(amount * n) time, O(amount) space
28+
29+
class Solution:
30+
def coinChange(self, coins: List[int], amount: int) -> int:
31+
dp = [0] + [amount + 1] * amount
32+
33+
for coin in coins:
34+
for i in range(coin, amount + 1):
35+
dp[i] = min(dp[i], dp[i - coin] + 1)
36+
37+
return dp[amount] if dp[amount] < amount + 1 else -1

coin-change/hi-rachel.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function coinChange(coins: number[], amount: number): number {
2+
const dp = [0, ...new Array(amount).fill(amount + 1)];
3+
for (let i = 0; i <= amount; i++) {
4+
for (const coin of coins) {
5+
if (coin <= i) {
6+
dp[i] = Math.min(dp[i], dp[i - coin] + 1);
7+
}
8+
}
9+
}
10+
return dp[amount] < amount + 1 ? dp[amount] : -1;
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# 회전된 오름차순 배열에서 최소값을 이진 탐색으로 찾아라
2+
3+
# O(N) time, O(1) space -> 시간 복잡도 충족 x
4+
class Solution:
5+
def findMin(self, nums: List[int]) -> int:
6+
for i in range(1, len(nums)):
7+
if nums[i - 1] > nums[i]:
8+
return nums[i]
9+
return nums[0]
10+
11+
12+
class Solution:
13+
14+
15+
# 이진 탐색 풀이
16+
# O(log n) time, O(1) space
17+
class Solution:
18+
def findMin(self, nums: List[int]) -> int:
19+
low, high = 1, len(nums) - 1
20+
while low <= high:
21+
mid = (low + high) // 2
22+
if nums[mid - 1] > nums[mid]:
23+
return nums[mid]
24+
if nums[0] < nums[mid]:
25+
low = mid + 1
26+
else:
27+
high = mid - 1
28+
return nums[0]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function findMin(nums: number[]): number {
2+
let low = 0,
3+
high = nums.length - 1;
4+
5+
while (low <= high) {
6+
let mid = Math.floor((low + high) / 2);
7+
if (nums[mid - 1] > nums[mid]) {
8+
return nums[mid]; // 회전이 일어난 곳
9+
}
10+
if (nums[0] < nums[mid]) {
11+
low = mid + 1; // 왼쪽은 이미 정렬되어 있어, 오른쪽으로 이동
12+
} else {
13+
high = mid - 1; // 왼쪽으로 이동
14+
}
15+
}
16+
return nums[0];
17+
}
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# O(n) time, 모든 노드를 한 번씩 방문
2+
# O(h) for DFS / O(w) for BFS space, DFS는 재귀 호출 깊이 (h = 트리 높이), BFS는 큐에 들어가는 최대 노드 수 (w = 최대 너비)
3+
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+
11+
12+
class TreeNode:
13+
def __init__(self, val=0, left=None, right=None):
14+
self.val = val
15+
self.left = left
16+
self.right = right
17+
18+
# BFS 풀이
19+
from collections import deque
20+
21+
class Solution:
22+
def maxDepth(self, root: Optional[TreeNode]) -> int:
23+
if not root:
24+
return 0
25+
26+
queue = deque([root])
27+
depth = 0
28+
29+
while queue:
30+
for _ in range(len(queue)):
31+
node = queue.popleft()
32+
if node.left:
33+
queue.append(node.left)
34+
if node.right:
35+
queue.append(node.right)
36+
depth += 1
37+
return depth
38+
39+
# DFS 풀이
40+
class Solution:
41+
def maxDepth(self, root: Optional[TreeNode]) -> int:
42+
if not root:
43+
return 0
44+
return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* class TreeNode {
4+
* val: number
5+
* left: TreeNode | null
6+
* right: TreeNode | null
7+
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
8+
* this.val = (val===undefined ? 0 : val)
9+
* this.left = (left===undefined ? null : left)
10+
* this.right = (right===undefined ? null : right)
11+
* }
12+
* }
13+
*/
14+
15+
// O(n) time, 모든 노드를 한 번씩 방문
16+
// O(h) for DFS / O(w) for BFS space, DFS는 재귀 호출 깊이 (h = 트리 높이), BFS는 큐에 들어가는 최대 노드 수 (w = 최대 너비)
17+
18+
class TreeNode {
19+
val: number;
20+
left: TreeNode | null;
21+
right: TreeNode | null;
22+
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
23+
this.val = val === undefined ? 0 : val;
24+
this.left = left === undefined ? null : left;
25+
this.right = right === undefined ? null : right;
26+
}
27+
}
28+
29+
// BFS 풀이
30+
function maxDepth(root: TreeNode | null): number {
31+
if (root === null) return 0;
32+
33+
const queue: TreeNode[] = [root];
34+
let depth = 0;
35+
36+
while (queue.length > 0) {
37+
const levelSize = queue.length;
38+
39+
for (let i = 0; i < levelSize; i++) {
40+
const node = queue.shift();
41+
if (node) {
42+
if (node.left) queue.push(node.left);
43+
if (node.right) queue.push(node.right);
44+
}
45+
}
46+
depth++;
47+
}
48+
return depth;
49+
}
50+
51+
// DFS 풀이
52+
// function maxDepth(root: TreeNode | null): number {
53+
// if (root === null) return 0;
54+
// const left = maxDepth(root.left);
55+
// const right = maxDepth(root.right);
56+
// return Math.max(left, right) + 1;
57+
// }

merge-two-sorted-lists/hi-rachel.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# O(n + m) time, n = list1의 노드 수 / m = list2의 노드 수
2+
# O(1) space, 연결된 새 리스트는 기존 노드들을 재사용해서 만듬
3+
4+
# Definition for singly-linked list.
5+
# class ListNode:
6+
# def __init__(self, val=0, next=None):
7+
# self.val = val
8+
# self.next = next
9+
10+
class ListNode:
11+
def __init__(self, val=0, next=None):
12+
self.val = val
13+
self.next = next
14+
15+
class Solution:
16+
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
17+
dummy = ListNode()
18+
tail = dummy
19+
20+
while list1 and list2:
21+
if list1.val < list2.val:
22+
tail.next = list1
23+
list1 = list1.next
24+
else:
25+
tail.next = list2
26+
list2 = list2.next
27+
tail = tail.next
28+
29+
if list1:
30+
tail.next = list1
31+
if list2:
32+
tail.next = list2
33+
return dummy.next

merge-two-sorted-lists/hi-rachel.ts

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Definition for singly-linked list.
3+
* class ListNode {
4+
* val: number
5+
* next: ListNode | null
6+
* constructor(val?: number, next?: ListNode | null) {
7+
* this.val = (val===undefined ? 0 : val)
8+
* this.next = (next===undefined ? null : next)
9+
* }
10+
* }
11+
*/
12+
13+
class ListNode {
14+
val: number;
15+
next: ListNode | null;
16+
constructor(val?: number, next?: ListNode | null) {
17+
this.val = val === undefined ? 0 : val;
18+
this.next = next === undefined ? null : next;
19+
}
20+
}
21+
22+
function mergeTwoLists(
23+
list1: ListNode | null,
24+
list2: ListNode | null
25+
): ListNode | null {
26+
const dummy = new ListNode();
27+
let tail = dummy;
28+
while (list1 !== null && list2 !== null) {
29+
if (list1.val < list2.val) {
30+
tail.next = list1;
31+
list1 = list1.next;
32+
} else {
33+
tail.next = list2;
34+
list2 = list2.next;
35+
}
36+
tail = tail.next;
37+
}
38+
if (list1 !== null) {
39+
tail.next = list1;
40+
}
41+
if (list2 !== null) {
42+
tail.next = list2;
43+
}
44+
return dummy.next;
45+
}

word-search/hi-rachel.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# DFS 풀이
2+
# board 높이: m, 넓이: n, w: 단어의 길이
3+
# TC: (m * n * 4^w) -> 4^w 상하좌우 탐색 * 글자판 내의 모든 좌표를 상대로 수행함
4+
# SC: O(m * n + w) -> traversing 집합 메모리는 글자판의 크기의 비례 + dfs 호출 스택의 깊이가 단어의 길이에 비례해 증가
5+
6+
class Solution:
7+
def exist(self, board: List[List[str]], word: str) -> bool:
8+
n_rows, n_cols = len(board), len(board[0])
9+
traversing = set()
10+
11+
def dfs(row, col, idx):
12+
if idx == len(word):
13+
return True
14+
if not (0 <= row < n_rows and 0 <= col < n_cols):
15+
return False
16+
if (row, col) in traversing:
17+
return False
18+
if board[row][col] != word[idx]:
19+
return False
20+
21+
traversing.add((row, col))
22+
# 상하좌우 탐색
23+
for (r, c) in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
24+
if dfs(row + r, col + c, idx + 1):
25+
return True
26+
traversing.remove((row, col))
27+
return False
28+
29+
for i in range(n_rows):
30+
for j in range(n_cols):
31+
if dfs(i, j, 0):
32+
return True
33+
return False

0 commit comments

Comments
 (0)