Skip to content

[hu6r1s] WEEK 04 Solutions #1812

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 6 commits into from
Aug 18, 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
63 changes: 63 additions & 0 deletions coin-change/hu6r1s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from collections import deque

class Solution:
"""
1. 가장 큰 수부터 차례대로 빼면서 확인 - 틀린 풀이
가장 큰 수부터 차례대로 빼면 안되는 경우가 있음
coins = [186,419,83,408], amount = 6249
이건 419부터 안될때까지 빼는 방식으로 되지 않음, 즉 최적의 금액을 찾아야 함.
그리디 같은 문제일 듯

"""
"""
def coinChange(self, coins: List[int], amount: int) -> int:
if amount == 0:
return 0

coins.sort(reverse=True)
result = 0
for coin in coins:
while amount >= coin:
amount -= coin
result += 1

if amount:
return -1
return result
"""
"""
- BFS를 사용하여 "동전 합"을 0에서 시작해 amount까지 도달하는 최소 단계를 탐색
- 큐의 원소: (cnt, total)
cnt : 현재까지 사용한 동전 개수
total : 현재까지 만든 합
- visited 집합으로 이미 방문한 합을 중복 탐색하지 않게 함
- 첫 번째로 amount에 도달하는 순간이 최소 동전 개수 (BFS 특성상)

시간 복잡도:
- 최악의 경우 모든 합(0 ~ amount)을 탐색하며,
각 합에서 최대 len(coins)개의 새로운 상태를 큐에 넣음
- O(amount × n), n = len(coins)

공간 복잡도:
- visited 집합: 최대 amount+1 크기
- 큐(queue): 최악의 경우 O(amount × n) 상태 저장 가능
- O(amount)
"""
def coinChange(self, coins: List[int], amount: int) -> int:
def bfs():
queue = deque([(0, 0)])
visited = set()
while queue:
cnt, total = queue.popleft()
if amount == total:
return cnt
if total in visited:
continue
visited.add(total)

for coin in coins:
if coin + total <= amount:
queue.append((cnt + 1, total + coin))
return -1

return bfs()
55 changes: 55 additions & 0 deletions find-minimum-in-rotated-sorted-array/hu6r1s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class Solution:
"""
[3, 4, 5, 1, 2] -> [2, 3, 4, 5, 1] -> [1, 2, 3, 4, 5]
1. 큐의 rotate 이용 -> 회전 전의 첫 요소가 회전 후의 요소 비교
시간복잡도: O(n^2)
- while 루프가 최대 n번 반복 가능
- deque.rotate(±1) 연산이 O(n) 시간 소요
- 따라서 전체는 O(n) * O(n) = O(n^2)
공간복잡도: O(n)
- 입력 배열을 deque로 변환 → 추가로 O(n) 공간 사용
- 나머지는 상수 공간
"""
"""
def findMin(self, nums: List[int]) -> int:
nums = deque(nums)
if len(nums) == 1:
return nums[0]

while True:
cur = nums[0]
nums.rotate(1)
if cur < nums[0]:
nums.rotate(-1)
return nums[0]
"""

"""
2. 요소별로 이전 값과 현재 값을 비교하여 작은 값이 나오면 그 값이 첫번쨰 요소, 즉 가장 작은 요소가 됨
시간복잡도: O(n)
- 최악의 경우 배열 전체를 한 번 순회해야 함
- n = len(nums)
공간복잡도: O(1)
- 추가로 사용하는 변수는 i와 몇 개의 상수형 변수뿐
"""
"""
def findMin(self, nums: List[int]) -> int:
for i in range(1, len(nums)):
if nums[i - 1] > nums[i]:
return nums[i]
return nums[0]
"""
"""
3. 이분탐색을 사용하는 방법
"""
def findMin(self, nums: List[int]) -> int:
start, end = 1, len(nums) - 1
while start <= end:
mid = (start + end) // 2
if nums[mid - 1] > nums[mid]:
return nums[mid]
if nums[0] < nums[mid]:
start = mid + 1
else:
end = mid - 1
return nums[0]
50 changes: 50 additions & 0 deletions maximum-depth-of-binary-tree/hu6r1s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from collections import deque

# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0

def bfs(n):
queue = deque([n])
depth = 0

while queue:
depth += 1
for _ in range(len(queue)):
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return depth

def dfs(n):
stack = [n]
max_depth = 0
visited = {n: 1}

while stack:
node = stack.pop()
depth = visited[node]
max_depth = max(max_depth, depth)
if node.left:
visited[node.left] = depth + 1
stack.append(node.left)
if node.right:
visited[node.right] = depth + 1
stack.append(node.right)
return max_depth

return dfs(root)


"""
bfs 방식으로 left나 right가 있으면 스택에 넣고 depth + 1, dfs보다 비효율인 듯
"""
26 changes: 26 additions & 0 deletions merge-two-sorted-lists/hu6r1s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
# 시간복잡도: O(n + m) -> 두 리스트의 모든 노드를 한 번씩 방문
# 공간복잡도: O(1) -> 기존 노드 재배치, 추가 메모리 거의 없음
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
merged_list = ListNode()
tail = merged_list

while list1 and list2:
if list1.val < list2.val:
tail.next = list1
list1 = list1.next
else:
tail.next = list2
list2 = list2.next
tail = tail.next

if list1:
Copy link
Contributor

Choose a reason for hiding this comment

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

-> tail.next = list1 if list1 else list2 로 간결히 작성 가능합니다

tail.next = list1
else:
tail.next = list2
return merged_list.next
46 changes: 46 additions & 0 deletions word-search/hu6r1s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class Solution:
"""
1. dfs 방식
dx = [1, -1, 0, 0], dy = [0, 0, 1, -1], visited = [[False] * m for _ in range(n)]
4방향으로 가면서 해당 요소에 단어가 없으면 false
방문한 적이 없어야 하고,

시간복잡도: O(N * L * 4^L)
- N: 보드 크기 (n*m)
- L: 단어 길이
- 모든 좌표에서 DFS 시작 (N회) × 4방향 분기 (4^L) × 슬라이싱 비용 (O(L))
공간복잡도: O(N + L^2)
- visited 배열 O(N)
- 재귀 호출 스택 O(L)
- 문자열 슬라이싱으로 인한 추가 메모리 O(L^2)

"""
def exist(self, board: List[List[str]], word: str) -> bool:
n, m = len(board), len(board[0])
visited = [[False] * m for _ in range(n)]
dx, dy = [1, -1, 0, 0], [0, 0, 1, -1]

def dfs(x, y, w):
if not w:
return True
if x < 0 or y < 0 or x >= n or y >= m:
return False
if visited[x][y] or board[x][y] != w[0]:
return False

visited[x][y] = True

for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if dfs(nx, ny, w[1:]):
return True

visited[x][y] = False
return False

for i in range(n):
for j in range(m):
if dfs(i, j, word):
return True
return False