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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
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