Skip to content

Commit

Permalink
Merge pull request #542 from lymchgmk/feat/week10
Browse files Browse the repository at this point in the history
[EGON] Week10 Solutions
  • Loading branch information
EgonD3V authored Oct 24, 2024
2 parents ef6bd30 + e9629f7 commit 64495db
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 0 deletions.
58 changes: 58 additions & 0 deletions course-schedule/EGON.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from collections import deque
from typing import List
from unittest import TestCase, main


class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
return self.solve_topological_sort(numCourses, prerequisites)

"""
Runtime: 1 ms (Beats 100.00%)
Time Complexity: o(c + p)
- graph 및 rank 갱신에 prerequisites의 길이 p만큼 조회하는데 O(p)
- queue의 초기 노드 삽입에 numCourses만큼 조회하는데 O(c)
- queue에서 위상 정렬로 탐색하는데 모든 노드와 간선을 조회하는데 O(c + p)
> O(p) + O(c) + O(c + p) ~= o(c + p)
Memory: 17.85 MB (Beats 99.94%)
Space Complexity: O(c)
- graph 변수 사용에 O(c + p)
- rank 변수 사용에 O(c)
- queue 변수 사용에서 최대 크기는 graph의 크기와 같으므로 O(c)
> O(c + p) + O(c) + O(c) ~= O(c + p)
"""
def solve_topological_sort(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = {i: [] for i in range(numCourses)}
rank = [0] * numCourses
for u, v in prerequisites:
graph[v].append(u)
rank[u] += 1

queue = deque()
for i in range(numCourses):
if rank[i] == 0:
queue.append(i)

count = 0
while queue:
node = queue.popleft()
count += 1
for neighbor in graph[node]:
rank[neighbor] -= 1
if rank[neighbor] == 0:
queue.append(neighbor)

return count == numCourses


class _LeetCodeTestCases(TestCase):
def test_1(self):
numCourses = 5
prerequisites = [[1,4],[2,4],[3,1],[3,2]]
output = True
self.assertEqual(Solution.canFinish(Solution(), numCourses, prerequisites), output)


if __name__ == '__main__':
main()
48 changes: 48 additions & 0 deletions invert-binary-tree/EGON.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from typing import Optional
from unittest import TestCase, main


# 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 invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
return self.solve_dfs(root)

"""
Runtime: 0 ms (Beats 100.00%)
Time Complexity: O(n)
> 트리의 모든 node를 방문하므로 O(n)
Memory: 16.53 MB (Beats 25.95%)
Space Complexity: O(n)
> stack의 최대 크기는 트리의 최장 경로를 이루는 node의 갯수이고, 최악의 경우 트리의 한 쪽으로 모든 node가 이어져있는 경우이므로 O(n), upper bound
"""
def solve_dfs(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root is None:
return root

stack = [root]
while stack:
curr_node = stack.pop()
curr_node.left, curr_node.right = curr_node.right, curr_node.left
if curr_node.left:
stack.append(curr_node.left)
if curr_node.right:
stack.append(curr_node.right)

return root


class _LeetCodeTestCases(TestCase):
def test_1(self):
return


if __name__ == '__main__':
main()
43 changes: 43 additions & 0 deletions jump-game/EGON.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from typing import List
from unittest import TestCase, main


class Solution:
def canJump(self, nums: List[int]) -> bool:
return self.solve_dp(nums)

"""
Runtime: 3130 ms (Beats 11.42%)
Time Complexity: O(n * m)
- dp 배열 생성에 nums의 길이 n 만큼 조회하는데 O(n)
- 생성한 dp 배열을 조회하는데 O(n)
- dp[i]에서 점프하는 범위에 의해 * O(2 * m)
> O(n) + O(n) * O(2 * m) ~= O(n * m)
Memory: 17.80 MB (Beats 72.54%)
Space Complexity: O(n)
> nums의 길이에 비례하는 dp 배열 하나만 사용, O(n)
"""
def solve_dp(self, nums: List[int]) -> bool:
dp = [True if i == 0 else False for i in range(len(nums))]
for i in range(len(nums)):
if dp[-1] is True:
return True

if dp[i] is True:
for jump in range(nums[i] + 1):
if 0 <= i + jump < len(dp):
dp[i + jump] = True

return dp[-1]


class _LeetCodeTestCases(TestCase):
def test_1(self):
nums = [2, 3, 1, 1, 4]
output = True
self.assertEqual(Solution.canJump(Solution(), nums), output)


if __name__ == '__main__':
main()
55 changes: 55 additions & 0 deletions merge-k-sorted-lists/EGON.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from heapq import heappush, heappop
from typing import List, Optional
from unittest import TestCase, main


class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next


class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
return self.solve_priority_queue(lists)

"""
Runtime: 7 ms (Beats 100.00%)
Time Complexity: O(n * m)
- lists의 길이 k만큼 조회에 O(k)
- 힙의 크기가 최대 k이므로, heappush에 * O(log k)
- heap의 크기는 최대 k이므로,
- heappop하는데 O(k * log k)
- heappush하는데 lists를 이루는 list를 이루는 모든 원소들의 총 갯수를 n이라 하면, O(n * log k)
> O(k * log k) + O(k * log k) + O(n * log k) ~= O(max(k, n) * log k) = O(n * log k)
Memory: 19.44 MB (Beats 58.42%)
Space Complexity: O(k)
> heap의 크기는 lists의 길이 k에 비례하므로, O(k)
"""
def solve_priority_queue(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
root = result = ListNode(None)
heap = []

for i in range(len(lists)):
if lists[i]:
heappush(heap, (lists[i].val, i, lists[i]))

while heap:
node = heappop(heap)
_, idx, result.next = node

result = result.next
if result.next:
heappush(heap, (result.next.val, idx, result.next))

return root.next


class _LeetCodeTestCases(TestCase):
def test_1(self):
self.assertEqual(True, True)


if __name__ == '__main__':
main()
67 changes: 67 additions & 0 deletions search-in-rotated-sorted-array/EGON.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from typing import List
from unittest import TestCase, main


class Solution:
def search(self, nums: List[int], target: int) -> int:
return self.solve_binary_search(nums, target)

"""
Runtime: 4 ms (Beats 100.00%)
Time Complexity: O(log n)
> nums를 이진탐색으로 조회하므로 O(log n)
Memory: 17.03 MB (Beats 10.00%)
Space Complexity: O(1)
> index를 위한 정수형 변수만 사용하므로 O(1)
"""
def solve_binary_search(self, nums: List[int], target: int) -> int:
lo, hi = 0, len(nums) - 1
while lo < hi:
mid = (lo + hi) // 2
if nums[mid] == target:
return mid

if nums[lo] <= nums[mid]:
if nums[lo] <= target <= nums[mid]:
hi = mid
else:
lo = mid + 1

else:
if nums[mid] <= target <= nums[hi]:
lo = mid + 1
else:
hi = mid

return lo if nums[lo] == target else -1


class _LeetCodeTestCases(TestCase):
def test_1(self):
nums = [4,5,6,7,0,1,2]
target = 0
output = 4
self.assertEqual(Solution.search(Solution(), nums, target), output)

def test_2(self):
nums = [4,5,6,7,0,1,2]
target = 3
output = -1
self.assertEqual(Solution.search(Solution(), nums, target), output)

def test_3(self):
nums = [1]
target = 0
output = -1
self.assertEqual(Solution.search(Solution(), nums, target), output)

def test_4(self):
nums = [3, 1]
target = 1
output = 1
self.assertEqual(Solution.search(Solution(), nums, target), output)


if __name__ == '__main__':
main()

0 comments on commit 64495db

Please sign in to comment.