Skip to content

Commit 64495db

Browse files
authored
Merge pull request DaleStudy#542 from lymchgmk/feat/week10
[EGON] Week10 Solutions
2 parents ef6bd30 + e9629f7 commit 64495db

File tree

5 files changed

+271
-0
lines changed

5 files changed

+271
-0
lines changed

course-schedule/EGON.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from collections import deque
2+
from typing import List
3+
from unittest import TestCase, main
4+
5+
6+
class Solution:
7+
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
8+
return self.solve_topological_sort(numCourses, prerequisites)
9+
10+
"""
11+
Runtime: 1 ms (Beats 100.00%)
12+
Time Complexity: o(c + p)
13+
- graph 및 rank 갱신에 prerequisites의 길이 p만큼 조회하는데 O(p)
14+
- queue의 초기 노드 삽입에 numCourses만큼 조회하는데 O(c)
15+
- queue에서 위상 정렬로 탐색하는데 모든 노드와 간선을 조회하는데 O(c + p)
16+
> O(p) + O(c) + O(c + p) ~= o(c + p)
17+
18+
Memory: 17.85 MB (Beats 99.94%)
19+
Space Complexity: O(c)
20+
- graph 변수 사용에 O(c + p)
21+
- rank 변수 사용에 O(c)
22+
- queue 변수 사용에서 최대 크기는 graph의 크기와 같으므로 O(c)
23+
> O(c + p) + O(c) + O(c) ~= O(c + p)
24+
"""
25+
def solve_topological_sort(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
26+
graph = {i: [] for i in range(numCourses)}
27+
rank = [0] * numCourses
28+
for u, v in prerequisites:
29+
graph[v].append(u)
30+
rank[u] += 1
31+
32+
queue = deque()
33+
for i in range(numCourses):
34+
if rank[i] == 0:
35+
queue.append(i)
36+
37+
count = 0
38+
while queue:
39+
node = queue.popleft()
40+
count += 1
41+
for neighbor in graph[node]:
42+
rank[neighbor] -= 1
43+
if rank[neighbor] == 0:
44+
queue.append(neighbor)
45+
46+
return count == numCourses
47+
48+
49+
class _LeetCodeTestCases(TestCase):
50+
def test_1(self):
51+
numCourses = 5
52+
prerequisites = [[1,4],[2,4],[3,1],[3,2]]
53+
output = True
54+
self.assertEqual(Solution.canFinish(Solution(), numCourses, prerequisites), output)
55+
56+
57+
if __name__ == '__main__':
58+
main()

invert-binary-tree/EGON.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from typing import Optional
2+
from unittest import TestCase, main
3+
4+
5+
# Definition for a binary tree node.
6+
class TreeNode:
7+
def __init__(self, val=0, left=None, right=None):
8+
self.val = val
9+
self.left = left
10+
self.right = right
11+
12+
13+
class Solution:
14+
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
15+
return self.solve_dfs(root)
16+
17+
"""
18+
Runtime: 0 ms (Beats 100.00%)
19+
Time Complexity: O(n)
20+
> 트리의 모든 node를 방문하므로 O(n)
21+
22+
Memory: 16.53 MB (Beats 25.95%)
23+
Space Complexity: O(n)
24+
> stack의 최대 크기는 트리의 최장 경로를 이루는 node의 갯수이고, 최악의 경우 트리의 한 쪽으로 모든 node가 이어져있는 경우이므로 O(n), upper bound
25+
"""
26+
def solve_dfs(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
27+
if root is None:
28+
return root
29+
30+
stack = [root]
31+
while stack:
32+
curr_node = stack.pop()
33+
curr_node.left, curr_node.right = curr_node.right, curr_node.left
34+
if curr_node.left:
35+
stack.append(curr_node.left)
36+
if curr_node.right:
37+
stack.append(curr_node.right)
38+
39+
return root
40+
41+
42+
class _LeetCodeTestCases(TestCase):
43+
def test_1(self):
44+
return
45+
46+
47+
if __name__ == '__main__':
48+
main()

jump-game/EGON.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from typing import List
2+
from unittest import TestCase, main
3+
4+
5+
class Solution:
6+
def canJump(self, nums: List[int]) -> bool:
7+
return self.solve_dp(nums)
8+
9+
"""
10+
Runtime: 3130 ms (Beats 11.42%)
11+
Time Complexity: O(n * m)
12+
- dp 배열 생성에 nums의 길이 n 만큼 조회하는데 O(n)
13+
- 생성한 dp 배열을 조회하는데 O(n)
14+
- dp[i]에서 점프하는 범위에 의해 * O(2 * m)
15+
> O(n) + O(n) * O(2 * m) ~= O(n * m)
16+
17+
Memory: 17.80 MB (Beats 72.54%)
18+
Space Complexity: O(n)
19+
> nums의 길이에 비례하는 dp 배열 하나만 사용, O(n)
20+
"""
21+
def solve_dp(self, nums: List[int]) -> bool:
22+
dp = [True if i == 0 else False for i in range(len(nums))]
23+
for i in range(len(nums)):
24+
if dp[-1] is True:
25+
return True
26+
27+
if dp[i] is True:
28+
for jump in range(nums[i] + 1):
29+
if 0 <= i + jump < len(dp):
30+
dp[i + jump] = True
31+
32+
return dp[-1]
33+
34+
35+
class _LeetCodeTestCases(TestCase):
36+
def test_1(self):
37+
nums = [2, 3, 1, 1, 4]
38+
output = True
39+
self.assertEqual(Solution.canJump(Solution(), nums), output)
40+
41+
42+
if __name__ == '__main__':
43+
main()

merge-k-sorted-lists/EGON.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from heapq import heappush, heappop
2+
from typing import List, Optional
3+
from unittest import TestCase, main
4+
5+
6+
class ListNode:
7+
def __init__(self, val=0, next=None):
8+
self.val = val
9+
self.next = next
10+
11+
12+
class Solution:
13+
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
14+
return self.solve_priority_queue(lists)
15+
16+
"""
17+
Runtime: 7 ms (Beats 100.00%)
18+
Time Complexity: O(n * m)
19+
- lists의 길이 k만큼 조회에 O(k)
20+
- 힙의 크기가 최대 k이므로, heappush에 * O(log k)
21+
- heap의 크기는 최대 k이므로,
22+
- heappop하는데 O(k * log k)
23+
- heappush하는데 lists를 이루는 list를 이루는 모든 원소들의 총 갯수를 n이라 하면, O(n * log k)
24+
> O(k * log k) + O(k * log k) + O(n * log k) ~= O(max(k, n) * log k) = O(n * log k)
25+
26+
Memory: 19.44 MB (Beats 58.42%)
27+
Space Complexity: O(k)
28+
> heap의 크기는 lists의 길이 k에 비례하므로, O(k)
29+
"""
30+
def solve_priority_queue(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
31+
root = result = ListNode(None)
32+
heap = []
33+
34+
for i in range(len(lists)):
35+
if lists[i]:
36+
heappush(heap, (lists[i].val, i, lists[i]))
37+
38+
while heap:
39+
node = heappop(heap)
40+
_, idx, result.next = node
41+
42+
result = result.next
43+
if result.next:
44+
heappush(heap, (result.next.val, idx, result.next))
45+
46+
return root.next
47+
48+
49+
class _LeetCodeTestCases(TestCase):
50+
def test_1(self):
51+
self.assertEqual(True, True)
52+
53+
54+
if __name__ == '__main__':
55+
main()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from typing import List
2+
from unittest import TestCase, main
3+
4+
5+
class Solution:
6+
def search(self, nums: List[int], target: int) -> int:
7+
return self.solve_binary_search(nums, target)
8+
9+
"""
10+
Runtime: 4 ms (Beats 100.00%)
11+
Time Complexity: O(log n)
12+
> nums를 이진탐색으로 조회하므로 O(log n)
13+
14+
Memory: 17.03 MB (Beats 10.00%)
15+
Space Complexity: O(1)
16+
> index를 위한 정수형 변수만 사용하므로 O(1)
17+
"""
18+
def solve_binary_search(self, nums: List[int], target: int) -> int:
19+
lo, hi = 0, len(nums) - 1
20+
while lo < hi:
21+
mid = (lo + hi) // 2
22+
if nums[mid] == target:
23+
return mid
24+
25+
if nums[lo] <= nums[mid]:
26+
if nums[lo] <= target <= nums[mid]:
27+
hi = mid
28+
else:
29+
lo = mid + 1
30+
31+
else:
32+
if nums[mid] <= target <= nums[hi]:
33+
lo = mid + 1
34+
else:
35+
hi = mid
36+
37+
return lo if nums[lo] == target else -1
38+
39+
40+
class _LeetCodeTestCases(TestCase):
41+
def test_1(self):
42+
nums = [4,5,6,7,0,1,2]
43+
target = 0
44+
output = 4
45+
self.assertEqual(Solution.search(Solution(), nums, target), output)
46+
47+
def test_2(self):
48+
nums = [4,5,6,7,0,1,2]
49+
target = 3
50+
output = -1
51+
self.assertEqual(Solution.search(Solution(), nums, target), output)
52+
53+
def test_3(self):
54+
nums = [1]
55+
target = 0
56+
output = -1
57+
self.assertEqual(Solution.search(Solution(), nums, target), output)
58+
59+
def test_4(self):
60+
nums = [3, 1]
61+
target = 1
62+
output = 1
63+
self.assertEqual(Solution.search(Solution(), nums, target), output)
64+
65+
66+
if __name__ == '__main__':
67+
main()

0 commit comments

Comments
 (0)