Skip to content

Commit edddfe9

Browse files
authored
Merge pull request #1812 from hu6r1s/main
[hu6r1s] WEEK 04 Solutions
2 parents 3c37151 + ca7f3b9 commit edddfe9

File tree

5 files changed

+240
-0
lines changed

5 files changed

+240
-0
lines changed

coin-change/hu6r1s.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from collections import deque
2+
3+
class Solution:
4+
"""
5+
1. 가장 큰 수부터 차례대로 빼면서 확인 - 틀린 풀이
6+
가장 큰 수부터 차례대로 빼면 안되는 경우가 있음
7+
coins = [186,419,83,408], amount = 6249
8+
이건 419부터 안될때까지 빼는 방식으로 되지 않음, 즉 최적의 금액을 찾아야 함.
9+
그리디 같은 문제일 듯
10+
11+
"""
12+
"""
13+
def coinChange(self, coins: List[int], amount: int) -> int:
14+
if amount == 0:
15+
return 0
16+
17+
coins.sort(reverse=True)
18+
result = 0
19+
for coin in coins:
20+
while amount >= coin:
21+
amount -= coin
22+
result += 1
23+
24+
if amount:
25+
return -1
26+
return result
27+
"""
28+
"""
29+
- BFS를 사용하여 "동전 합"을 0에서 시작해 amount까지 도달하는 최소 단계를 탐색
30+
- 큐의 원소: (cnt, total)
31+
cnt : 현재까지 사용한 동전 개수
32+
total : 현재까지 만든 합
33+
- visited 집합으로 이미 방문한 합을 중복 탐색하지 않게 함
34+
- 첫 번째로 amount에 도달하는 순간이 최소 동전 개수 (BFS 특성상)
35+
36+
시간 복잡도:
37+
- 최악의 경우 모든 합(0 ~ amount)을 탐색하며,
38+
각 합에서 최대 len(coins)개의 새로운 상태를 큐에 넣음
39+
- O(amount × n), n = len(coins)
40+
41+
공간 복잡도:
42+
- visited 집합: 최대 amount+1 크기
43+
- 큐(queue): 최악의 경우 O(amount × n) 상태 저장 가능
44+
- O(amount)
45+
"""
46+
def coinChange(self, coins: List[int], amount: int) -> int:
47+
def bfs():
48+
queue = deque([(0, 0)])
49+
visited = set()
50+
while queue:
51+
cnt, total = queue.popleft()
52+
if amount == total:
53+
return cnt
54+
if total in visited:
55+
continue
56+
visited.add(total)
57+
58+
for coin in coins:
59+
if coin + total <= amount:
60+
queue.append((cnt + 1, total + coin))
61+
return -1
62+
63+
return bfs()
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
class Solution:
2+
"""
3+
[3, 4, 5, 1, 2] -> [2, 3, 4, 5, 1] -> [1, 2, 3, 4, 5]
4+
1. 큐의 rotate 이용 -> 회전 전의 첫 요소가 회전 후의 요소 비교
5+
시간복잡도: O(n^2)
6+
- while 루프가 최대 n번 반복 가능
7+
- deque.rotate(±1) 연산이 O(n) 시간 소요
8+
- 따라서 전체는 O(n) * O(n) = O(n^2)
9+
공간복잡도: O(n)
10+
- 입력 배열을 deque로 변환 → 추가로 O(n) 공간 사용
11+
- 나머지는 상수 공간
12+
"""
13+
"""
14+
def findMin(self, nums: List[int]) -> int:
15+
nums = deque(nums)
16+
if len(nums) == 1:
17+
return nums[0]
18+
19+
while True:
20+
cur = nums[0]
21+
nums.rotate(1)
22+
if cur < nums[0]:
23+
nums.rotate(-1)
24+
return nums[0]
25+
"""
26+
27+
"""
28+
2. 요소별로 이전 값과 현재 값을 비교하여 작은 값이 나오면 그 값이 첫번쨰 요소, 즉 가장 작은 요소가 됨
29+
시간복잡도: O(n)
30+
- 최악의 경우 배열 전체를 한 번 순회해야 함
31+
- n = len(nums)
32+
공간복잡도: O(1)
33+
- 추가로 사용하는 변수는 i와 몇 개의 상수형 변수뿐
34+
"""
35+
"""
36+
def findMin(self, nums: List[int]) -> int:
37+
for i in range(1, len(nums)):
38+
if nums[i - 1] > nums[i]:
39+
return nums[i]
40+
return nums[0]
41+
"""
42+
"""
43+
3. 이분탐색을 사용하는 방법
44+
"""
45+
def findMin(self, nums: List[int]) -> int:
46+
start, end = 1, len(nums) - 1
47+
while start <= end:
48+
mid = (start + end) // 2
49+
if nums[mid - 1] > nums[mid]:
50+
return nums[mid]
51+
if nums[0] < nums[mid]:
52+
start = mid + 1
53+
else:
54+
end = mid - 1
55+
return nums[0]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from collections import deque
2+
3+
# Definition for a binary tree node.
4+
# class TreeNode:
5+
# def __init__(self, val=0, left=None, right=None):
6+
# self.val = val
7+
# self.left = left
8+
# self.right = right
9+
class Solution:
10+
def maxDepth(self, root: Optional[TreeNode]) -> int:
11+
if not root:
12+
return 0
13+
14+
def bfs(n):
15+
queue = deque([n])
16+
depth = 0
17+
18+
while queue:
19+
depth += 1
20+
for _ in range(len(queue)):
21+
node = queue.popleft()
22+
if node.left:
23+
queue.append(node.left)
24+
if node.right:
25+
queue.append(node.right)
26+
return depth
27+
28+
def dfs(n):
29+
stack = [n]
30+
max_depth = 0
31+
visited = {n: 1}
32+
33+
while stack:
34+
node = stack.pop()
35+
depth = visited[node]
36+
max_depth = max(max_depth, depth)
37+
if node.left:
38+
visited[node.left] = depth + 1
39+
stack.append(node.left)
40+
if node.right:
41+
visited[node.right] = depth + 1
42+
stack.append(node.right)
43+
return max_depth
44+
45+
return dfs(root)
46+
47+
48+
"""
49+
bfs 방식으로 left나 right가 있으면 스택에 넣고 depth + 1, dfs보다 비효율인 듯
50+
"""

merge-two-sorted-lists/hu6r1s.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Definition for singly-linked list.
2+
# class ListNode:
3+
# def __init__(self, val=0, next=None):
4+
# self.val = val
5+
# self.next = next
6+
class Solution:
7+
# 시간복잡도: O(n + m) -> 두 리스트의 모든 노드를 한 번씩 방문
8+
# 공간복잡도: O(1) -> 기존 노드 재배치, 추가 메모리 거의 없음
9+
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
10+
merged_list = ListNode()
11+
tail = merged_list
12+
13+
while list1 and list2:
14+
if list1.val < list2.val:
15+
tail.next = list1
16+
list1 = list1.next
17+
else:
18+
tail.next = list2
19+
list2 = list2.next
20+
tail = tail.next
21+
22+
if list1:
23+
tail.next = list1
24+
else:
25+
tail.next = list2
26+
return merged_list.next

word-search/hu6r1s.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
class Solution:
2+
"""
3+
1. dfs 방식
4+
dx = [1, -1, 0, 0], dy = [0, 0, 1, -1], visited = [[False] * m for _ in range(n)]
5+
4방향으로 가면서 해당 요소에 단어가 없으면 false
6+
방문한 적이 없어야 하고,
7+
8+
시간복잡도: O(N * L * 4^L)
9+
- N: 보드 크기 (n*m)
10+
- L: 단어 길이
11+
- 모든 좌표에서 DFS 시작 (N회) × 4방향 분기 (4^L) × 슬라이싱 비용 (O(L))
12+
공간복잡도: O(N + L^2)
13+
- visited 배열 O(N)
14+
- 재귀 호출 스택 O(L)
15+
- 문자열 슬라이싱으로 인한 추가 메모리 O(L^2)
16+
17+
"""
18+
def exist(self, board: List[List[str]], word: str) -> bool:
19+
n, m = len(board), len(board[0])
20+
visited = [[False] * m for _ in range(n)]
21+
dx, dy = [1, -1, 0, 0], [0, 0, 1, -1]
22+
23+
def dfs(x, y, w):
24+
if not w:
25+
return True
26+
if x < 0 or y < 0 or x >= n or y >= m:
27+
return False
28+
if visited[x][y] or board[x][y] != w[0]:
29+
return False
30+
31+
visited[x][y] = True
32+
33+
for i in range(4):
34+
nx = x + dx[i]
35+
ny = y + dy[i]
36+
if dfs(nx, ny, w[1:]):
37+
return True
38+
39+
visited[x][y] = False
40+
return False
41+
42+
for i in range(n):
43+
for j in range(m):
44+
if dfs(i, j, word):
45+
return True
46+
return False

0 commit comments

Comments
 (0)