Skip to content

Commit 68044c0

Browse files
authored
Merge pull request DaleStudy#1013 from dusunax/main
[οΏ½SunaDu] Week 10
2 parents 1a97465 + 869e90b commit 68044c0

File tree

3 files changed

+294
-0
lines changed

3 files changed

+294
-0
lines changed

β€Žcourse-schedule/dusunax.py

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
'''
2+
# 207
3+
μ°Έκ³  μ˜μƒ: https://www.youtube.com/watch?v=EgI5nU9etnU
4+
문제 풀이: https://www.algodale.com/problems/course-schedule/
5+
6+
## 문제 정리
7+
πŸ‘‰ prerequisitesλž€? ν•„μˆ˜ μ„ μˆ˜ κ³Όλͺ©μ΄λ‹€.
8+
πŸ‘‰ λ°©ν–₯성이 μžˆλŠ” μ—°κ²° κ΄€κ³„μ΄λ―€λ‘œ, Directed Graphλ‹€.
9+
πŸ‘‰ Cycle λ°œμƒ μ‹œ, μ½”μŠ€λ₯Ό μ΄μˆ˜ν•  수 μ—†λ‹€.(μ„œλ‘œ μ˜μ‘΄ν•˜λŠ” μˆœν™˜μ΄ μžˆμ–΄μ„œ 끝없이 돌게 λ˜λŠ” 경우)
10+
11+
## ν•΄κ²° 방식 두가지
12+
1. BFS, Queue, Topological Sort: μœ„μƒ μ •λ ¬
13+
2. DFS, Cycle Detection: μˆœν™˜ 탐지
14+
15+
### μœ„μƒ μ •λ ¬(Topological Sort) - BFS, Queue
16+
- μ§„μž… 차수(indegree): λ…Έλ“œλ‘œ λ“€μ–΄μ˜€λŠ” ν™”μ‚΄ν‘œ 수
17+
- κ·Έλž˜ν”„λ‘œ 인접 리슀트 ꡬ성
18+
- Queue에 λ„£κΈ°
19+
- Queue BFS 탐색
20+
- λͺ¨λ“  κ³Όλͺ©μ„ λ“€μ—ˆλŠ”μ§€ 확인
21+
22+
### μˆœν™˜ 탐지(Cycle Detection) - DFS
23+
- κ·Έλž˜ν”„λ‘œ 인접 리슀트 ꡬ성
24+
- λ°©λ¬Έ μƒνƒœ λ°°μ—΄ μ΄ˆκΈ°ν™”
25+
- dfs ν•¨μˆ˜
26+
- λͺ¨λ“  λ…Έλ“œμ— λŒ€ν•΄ dfs μ‹€ν–‰
27+
28+
## TC & SC
29+
- μ‹œκ°„ λ³΅μž‘λ„μ™€ 곡간 λ³΅μž‘λ„λŠ” O(V + E)둜 λ™μΌν•˜λ‹€.
30+
```
31+
V: λ…Έλ“œ 수(κ³Όλͺ© 수)
32+
E: κ°„μ„  수(μ„ μˆ˜ κ³Όλͺ© 관계 수)
33+
```
34+
35+
### TC is O(V + E)
36+
37+
두 방법 λͺ¨λ‘, κ·Έλž˜ν”„μ˜ λͺ¨λ“  λ…Έλ“œμ™€ 간선을 ν•œ λ²ˆμ”© 확인함
38+
- BFS: λͺ¨λ“  Vλ₯Ό μˆœνšŒν•˜λ©΄μ„œ, 각 λ…Έλ“œμ—μ„œ λ‚˜κ°€λŠ” Eλ₯Ό 따라가며 차수λ₯Ό μ€„μž„
39+
- DFS: λͺ¨λ“  Vλ₯Ό μˆœνšŒν•˜λ©΄μ„œ, 각 λ…Έλ“œμ—μ„œ μ—°κ²°λœ Eλ₯Ό 따라가며 깊이 탐색
40+
41+
### SC is O(V + E)
42+
- O(V+E): V + Eλ₯Ό μ €μž₯ν•˜λŠ” 인접 리슀트 κ·Έλž˜ν”„
43+
- O(V)'s: λ°©λ¬Έ μƒνƒœ μ €μž₯, μ§„μž… 차수 λ°°μ—΄, BFS 큐, DFS 호좜 μŠ€νƒ
44+
45+
## μœ„μƒμ •λ ¬(BFS) vs μˆœν™˜νƒμ§€(DFS)πŸ€”
46+
47+
### BFSλ₯Ό μ‚¬μš©ν–ˆμ„ λ•Œ
48+
- λ°˜λ³΅λ¬Έμ„ μ‚¬μš©ν•œ BFSκ°€ indegree(μ§„μž…μ°¨μˆ˜) κ°œλ…μ΄ 보닀 μ§κ΄€μ μ΄λ―€λ‘œ => "μˆœμ„œλŒ€λ‘œ μ²˜λ¦¬ν•  수 μžˆλŠ”μ§€ 확인"ν•  λ•Œ λͺ…ν™•ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€. μ§„μž… μ°¨μˆ˜κ°€ 0인 λ…Έλ“œλΆ€ν„° μ‹œμž‘ν•΄μ„œ 처리
49+
- μ„ μˆ˜ κ³Όλͺ©μ„ λ‹€ 듀은 κ³Όλͺ©μ€ μ§„μž… μ°¨μˆ˜κ°€ 0이 λ˜λ―€λ‘œ λ“€μ–΄κ°ˆ 수 μžˆλŠ” κ³Όλͺ©μ΄λΌλŠ” 점이 λͺ…확함
50+
```
51+
ν‚€μ›Œλ“œ: 처리 μˆœμ„œλ₯Ό 좜λ ₯, μˆœμ„œλŒ€λ‘œ μ²˜λ¦¬ν•  수 μžˆλŠ”μ§€
52+
```
53+
54+
### DFSλ₯Ό μ‚¬μš©ν–ˆμ„ λ•Œ
55+
- DFS μˆœν™˜ νƒμ§€λŠ” "μˆœν™˜ μ—¬λΆ€"κ°€ 핡심일 λ•Œ μžμ—°μŠ€λŸ½λ‹€.
56+
- μƒνƒœ(Status)λ₯Ό μ‚¬μš©ν•΄μ„œ, λ°©λ¬Έ 쀑인 λ…Έλ“œ μƒνƒœλ₯Ό λ‹€μ‹œ λ°©λ¬Έν•œλ‹€λ©΄ μˆœν™˜μ΄ μžˆμŒμ„ λ°”λ‘œ μ•Œ 수 μžˆλ‹€.
57+
- μˆœν™˜μ΄ 발견되면 λ°”λ‘œ μ€‘λ‹¨ν•˜λ―€λ‘œ, μˆœν™˜ 탐지에 μžμ—°μŠ€λŸ½λ‹€.
58+
```
59+
ν‚€μ›Œλ“œ: 사이클이 μžˆλŠ”μ§€ νŒλ‹¨
60+
```
61+
62+
### +a) `@cache`λ₯Ό ν™œμš©ν•΄λ³΄μž.
63+
- νŒŒμ΄μ„  3.9~ λ©”λͺ¨μ΄μ œμ΄μ…˜ ν•¨μˆ˜
64+
- 순수 ν•¨μˆ˜ + μž¬κ·€ μ΅œμ ν™”μ— μ‚¬μš© (μ™ΈλΆ€ μ˜μ‘΄μ„±, λΆ€μˆ˜νš¨κ³Όμ— μ£Όμ˜ν•  것)
65+
'''
66+
from enum import Enum
67+
68+
class Status(Enum): # use it to dfs
69+
INITIAL = 1
70+
IN_PROGRESS = 2
71+
FINISHED = 3
72+
73+
class Solution:
74+
'''
75+
1. BFS
76+
μœ„μƒ μ •λ ¬
77+
'''
78+
def canFinishTopologicalSort(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
79+
indegree = [0] * numCourses
80+
graph = defaultdict(list)
81+
82+
for dest, src in prerequisites:
83+
graph[src].append(dest)
84+
indegree[dest] += 1
85+
86+
queue = deque([i for i in range(numCourses) if indegree[i] == 0])
87+
processed_count = 0
88+
89+
while queue:
90+
node = queue.popleft()
91+
processed_count += 1
92+
for neighbor in graph[node]:
93+
indegree[neighbor] -= 1
94+
if indegree[neighbor] == 0:
95+
queue.append(neighbor)
96+
97+
return processed_count == numCourses
98+
99+
'''
100+
2. DFS
101+
μˆœν™˜ 탐지
102+
'''
103+
def canFinishCycleDetection(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
104+
graph = defaultdict(list)
105+
106+
for dest, src in prerequisites:
107+
graph[src].append(dest)
108+
109+
statuses = {i: Status.INITIAL for i in range(numCourses)}
110+
111+
def dfs(node):
112+
if statuses[node] == Status.IN_PROGRESS:
113+
return False
114+
if statuses[node] == Status.FINISHED:
115+
return True
116+
117+
statuses[node] = Status.IN_PROGRESS
118+
for neighbor in graph[node]:
119+
if not dfs(neighbor):
120+
return False
121+
statuses[node] = Status.FINISHED
122+
return True
123+
124+
return all(dfs(crs) for crs in range(numCourses))
125+
126+
'''
127+
3. @cache
128+
129+
파이썬 3.9 μ΄μƒμ—μ„œ μ‚¬μš©ν•˜λŠ” λ©”λͺ¨μ΄μ œμ΄μ…˜ λ°μ½”λ ˆμ΄ν„°
130+
- 동일 μž…λ ₯ -> 동일 좜λ ₯을 보μž₯ν•œλ‹€.
131+
- 128개 κΉŒμ§€λ§Œ μ €μž₯ν•˜λŠ” @lru_cache도 μžˆλ‹€.
132+
'''
133+
def canFinishWithCache(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
134+
graph = defaultdict(list)
135+
136+
for dest, src in prerequisites:
137+
graph[src].append(dest)
138+
139+
traversing = set()
140+
141+
@cache
142+
def dfs(node):
143+
if node in traversing:
144+
return False
145+
146+
traversing.add(node)
147+
result = all(dfs(pre) for pre in graph[node])
148+
traversing.remove(node)
149+
return result
150+
151+
return all(dfs(node) for node in range(numCourses))
152+
153+
'''
154+
4. visitedκ³Ό ν•¨κ»˜ μ‚¬μš©ν•˜κΈ°
155+
156+
@cache λ°μ½”λ ˆμ΄ν„°λŠ” λ©”λͺ¨μ΄μ œμ΄μ…˜, 같은 μž…λ ₯값에 따라 같은 κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜κ²Œν•¨
157+
κ²°κ³Όκ°€ λ³€ν•˜μ§€ μ•Šμ„ λ•Œ μœ μš©ν•¨ => dfs(node)λŠ” μ™ΈλΆ€ μƒνƒœ μˆœν™˜ traversing에 μ˜μ‘΄ν•΄μ„œ λ™μž‘μ΄ λ‹¬λΌμ§ˆ 수 μžˆλ‹€.
158+
λ”°λΌμ„œ visited set이 더 μžμ—°μŠ€λŸ¬μšΈ 수 μžˆλ‹€
159+
'''
160+
def canFinishWithVisited(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
161+
graph = defaultdict(list)
162+
163+
for dest, src in prerequisites:
164+
graph[src].append(dest)
165+
166+
traversing = set()
167+
visited = set()
168+
169+
def dfs(node):
170+
if node in traversing:
171+
return False
172+
if node in visited:
173+
return True
174+
175+
traversing.add(node)
176+
for pre in graph[node]:
177+
if not dfs(pre):
178+
return False
179+
traversing.remove(node)
180+
181+
visited.add(node)
182+
return True
183+
184+
return all(dfs(i) for i in range(numCourses))

β€Žinvert-binary-tree/dusunax.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'''
2+
# 226. Invert Binary Tree
3+
4+
switch left and right child of each node
5+
6+
## TC: O(N)
7+
8+
visit each node once
9+
10+
## SC: O(h)
11+
12+
h is height of tree
13+
14+
- best case: O(logN), balanced tree
15+
- worst case: O(N), skewed tree
16+
'''
17+
class Solution:
18+
'''
19+
DFS
20+
'''
21+
def invertTreeRecursive(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
22+
if not root:
23+
return None
24+
25+
root.left, root.right = root.right, root.left
26+
27+
self.invertTree(root.left)
28+
self.invertTree(root.right)
29+
30+
return root
31+
32+
'''
33+
BFS
34+
- 직관적인 stack 풀이
35+
'''
36+
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
37+
stack = [root]
38+
39+
while stack:
40+
node = stack.pop()
41+
if not node:
42+
continue
43+
44+
node.left, node.right = node.right, node.left
45+
stack.append(node.left)
46+
stack.append(node.right)
47+
48+
return root
49+
50+
'''
51+
- 참고용 deque 풀이
52+
'''
53+
def invertTreeDeque(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
54+
dq = deque([root])
55+
56+
while dq:
57+
node = dq.popleft()
58+
if not node:
59+
continue
60+
61+
node.left, node.right = node.right, node.left
62+
dq.append(node.left)
63+
dq.append(node.right)
64+
65+
return root
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'''
2+
# 33. Search in Rotated Sorted Array
3+
4+
binary search + condition check
5+
6+
이진 탐색 쀑, μ™Όμͺ½μ΄ μ •λ ¬λ˜μ—ˆμ„ λ•Œ
7+
- νƒ€κ²Ÿμ΄ μ •λ ¬λœ μ™Όμͺ½μ— μžˆλŠ” 경우, μ™Όμͺ½ 탐색 (leftλΆ€ν„° mid - 1 μ‚¬μ΄μ—μ„œ νƒ€κ²Ÿμ„ 탐색)
8+
- νƒ€κ²Ÿμ΄ μ •λ ¬λœ μ™Όμͺ½μ— 없을 경우, 였λ₯Έμͺ½ 탐색 (mid + 1λΆ€ν„° right μ‚¬μ΄μ—μ„œ νƒ€κ²Ÿμ„ 탐색)
9+
10+
이진 탐색 쀑, 였λ₯Έμͺ½μ΄ μ •λ ¬λ˜μ—ˆμ„ λ•Œ
11+
- νƒ€κ²Ÿμ΄ μ •λ ¬λœ 였λ₯Έμͺ½μ— μžˆλŠ” 경우, 였λ₯Έμͺ½ 탐색 (mid + 1λΆ€ν„° right μ‚¬μ΄μ—μ„œ νƒ€κ²Ÿμ„ 탐색)
12+
- νƒ€κ²Ÿμ΄ μ •λ ¬λœ 였λ₯Έμͺ½μ— 없을 경우, μ™Όμͺ½ 탐색 (leftλΆ€ν„° mid - 1 μ‚¬μ΄μ—μ„œ νƒ€κ²Ÿμ„ 탐색)
13+
14+
## TC: O(log n)
15+
16+
binary search
17+
18+
## SC: O(1)
19+
20+
no extra space
21+
22+
'''
23+
class Solution:
24+
def search(self, nums: List[int], target: int) -> int:
25+
left = 0
26+
right = len(nums) - 1
27+
28+
while left <= right:
29+
mid = left + (right - left) // 2
30+
31+
if nums[mid] == target:
32+
return mid
33+
34+
if nums[left] <= nums[mid]: # is_left_sorted
35+
if nums[left] <= target < nums[mid]: # is_target_left
36+
right = mid - 1
37+
else:
38+
left = mid + 1
39+
else:
40+
if nums[mid] < target <= nums[right]: # is_target_right
41+
left = mid + 1
42+
else:
43+
right = mid - 1
44+
45+
return -1

0 commit comments

Comments
Β (0)