[parkhojeong] WEEK 10 Solutions - #2844
Conversation
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
course-schedule/parkhojeong.py
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
course_to_precourses: dict[str, set[int]] = {}
precourse_to_courses: dict[str, set[int]] = {}
for course, pre_course in prerequisites:
if course not in course_to_precourses:
course_to_precourses[course] = set()
course_to_precourses[course].add(pre_course)
if pre_course not in precourse_to_courses:
precourse_to_courses[pre_course] = set()
precourse_to_courses[pre_course].add(course)
stack = []
for course in range(numCourses):
if course not in course_to_precourses:
stack.append(course)
while stack:
pre_course = stack.pop()
if pre_course in precourse_to_courses:
for course in precourse_to_courses[pre_course]:
course_to_precourses[course].remove(pre_course)
if len(course_to_precourses[course]) == 0:
stack.append(course)
for course in course_to_precourses:
if len(course_to_precourses[course]) != 0:
return False
return True- 패턴: Topological Sort, Hash Map / Hash Set
- 설명: Prerequisite 그래프에서 위상정렬(Topological Sort)을 사용해 순환 여부를 판단한다. 각 강의의 선행 과목을 관리하고, 진입 차수가 0인 노드를 제거하며 사이클 존재 여부를 검사한다. 해시 맵과 집합으로 그래프 정보를 유지한다.
📊 시간/공간 복잡도 분석
ℹ️ 이 파일에는 4가지 풀이가 포함되어 있어 각각 분석합니다.
풀이 1: Solution.canFinish — Time: O(V + E) / Space: O(V + E)
| 복잡도 | |
|---|---|
| Time | O(V + E) |
| Space | O(V + E) |
피드백: 모든 간선 정보를 양방향 맵으로 구성하고, 진입 차수가 0인 노드부터 차례로 제거하며 사이클 여부를 확인한다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: Solution.invertTree — Time: O(n) / Space: O(h)
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(h) |
피드백: 각 노드를 한 번씩 방문하고 스택/재귀를 통해 자식들을 처리한다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 3: Solution.canJump — Time: O(n) / Space: O(1)
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(1) |
피드백: 선형 스캔으로 가능성을 확인하므로 최악의 경우에도 한 번의 패스가 필요하다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 4: Solution.mergeKLists — Time: O(k n) / Space: O(1)
| 복잡도 | |
|---|---|
| Time | O(k n) |
| Space | O(1) |
피드백: 각 단계에서 최소 값을 찾는 선형 스캔으로 비효율적이다. 히드드 리스트나 우선순위 큐를 활용하면 개선됩니다.
개선 제안: 고려해볼 만한 대안: 힙을 이용한 병합으로 시간 복잡도를 O(n log k)로 낮출 수 있습니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
invert-binary-tree/parkhojeong.py
# 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]:
if not root:
return root
def dfs(node: Optional[TreeNode]):
node.right, node.left = node.left, node.right
if node.left:
dfs(node.left)
if node.right:
dfs(node.right)
dfs(root)
return root- 패턴: Depth-First Search, Binary Search
- 설명: 코드에서 이진 트리를 재귀적으로 방문하며 노드의 좌우를 교환하는 DFS 방식의 트리 순회 패턴이 사용됩니다. 트리의 각 노드에 대해 좌우를 스왑하고 재귀적으로 자식 노드로 내려가는 구조입니다.
📊 parkhojeong 님의 학습 현황이번 주 제출 문제
누적 학습 요약
문제 풀이 현황
🤖 이 댓글은 GitHub App을 통해 자동으로 작성되었습니다. 🔢 API 사용량 (gpt-5-nano)
|
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
jump-game/parkhojeong.py
class Solution:
def canJump(self, nums: List[int]) -> bool:
max_jump = 0
i = 0
arr = [0] * len(nums)
while i <= max_jump:
num = nums[i]
for j in range(min(num + i, len(nums) - 1), i - 1, -1):
if arr[j] == 1:
break
arr[j] = 1
max_jump = max(max_jump, j)
i += 1
return len(nums) - 1 == max_jump- 패턴: Greedy, Dynamic Programming
- 설명: 배열의 최대 도달 위치를 추적하며 현재 위치에서 가능한 여러 점에 도달 여부를 기록하는 방식으로 최댓값 갱신. 도달 여부를 배열으로 저장하고, 한 위치에서 다른 위치로 확장하는 점에서 DP/그리디의 혼합 패턴으로 해석 가능.
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
merge-k-sorted-lists/parkhojeong.py
# Definition for singly-linked list.
# 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]:
if len(lists) == 0:
return
if sum([1 if node is None else 0 for node in lists]) == len(lists):
return
def find_min():
idx = -1
min_val = sys.maxsize
i = 0
for l in lists:
if l is not None and min_val > l.val:
min_val = l.val
idx = i
i += 1
return idx
idx = find_min()
node = lists[idx]
head = node
lists[idx] = lists[idx].next
while node:
idx = find_min()
if idx == -1:
break
node.next = lists[idx]
node = node.next
lists[idx] = lists[idx].next
return head- 패턴: Two Pointers, Heap / Priority Queue
- 설명: 리스트의 각 노드를 차례대로 비교해 가장 작은 값을 선택하여 연결하는 방식으로, 여러 리스트의 노드를 하나의 정렬된 리스트로 병합한다. 매 단계에서 최소 원소를 찾는 탐색과 연결 포인터를 이동시키는 패턴이 두 포인터/힙 대기열의 아이디어와 유사하다.
There was a problem hiding this comment.
특정 배열에서 동적으로 최소값을 찾는 자료구조가 있죠!
지금은 3000ms정도 시간이 소요되는데 이건 "출제자가 배우길 의도한 정답" 과는 좀 거리가 있을 것 같습니다.
시간복잡도를 최적화 해 보시는 것을 시도해 보시면 좋겠네요!
There was a problem hiding this comment.
최적화 하시면 5~11ms정도로 가능하십니다!
There was a problem hiding this comment.
해당 풀이는 Amortized O(N)에 가깝긴 하지만 개인적으로 불필요한 부분 ( 가장 멀리 갈수 있는 거리만 확인하면 되는데 모든 거리에 대해 갈수 있는지 여부를 확인함 ) 이 저장되어 있다는게 맘에 걸리네요
실제로 최적화시 시간은 4배가량 빨라질수 있고 공간 복잡도 또한 추가공간 O(1)에 가능하십니다.
There was a problem hiding this comment.
제 생각에 DFS 함수를 개별 구현하지 않고 invertTree 메서드 자체에서 바로 재귀하는것이 더 낫지 않을까? 싶습니다.
답안 제출 문제
작성자 체크 리스트
In Review로 설정해주세요.검토자 체크 리스트
Important
본인 답안 제출 뿐만 아니라 다른 분 PR 하나 이상을 반드시 검토를 해주셔야 합니다!