-
-
Notifications
You must be signed in to change notification settings - Fork 361
[alphaorderly] WEEK 11 Solutions #2846
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # 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 | ||
| """ | ||
| 시간복잡도: O(n) | ||
| 공간복잡도: O(n) | ||
| """ | ||
| class Solution: | ||
| def maxPathSum(self, root: Optional[TreeNode]) -> int: | ||
| def calc(node: Optional[TreeNode]): | ||
| if not node: | ||
| # (한쪽 서브트리에서 root를 향해 올라오는 경로의 최대합, | ||
| # 해당 서브트리 내 임의 경로의 최대 합) | ||
| return (-float("inf"), -float("inf")) | ||
|
|
||
| # 왼쪽 서브트리 결과 | ||
| # left: 왼쪽 자식으로부터 root를 향해 이어질 수 있는 단일 경로의 최대 합 | ||
| # left_root: 왼쪽 서브트리 전체에서 얻을 수 있는 임의 경로의 최대 합 | ||
| left, left_root = calc(node.left) | ||
|
|
||
| # 오른쪽 서브트리 결과 | ||
| # right: 오른쪽 자식으로부터 root를 향해 이어질 수 있는 단일 경로의 최대 합 | ||
| # right_root: 오른쪽 서브트리 전체에서 얻을 수 있는 임의 경로의 최대 합 | ||
| right, right_root = calc(node.right) | ||
|
|
||
| # 한쪽(왼쪽/오른쪽) 또는 아무쪽도 안타거나(0) 현재노드로 연결 가능, 단일 경로 최대 합 | ||
| current = max(left, right, 0) + node.val | ||
| # 현재 노드를 루트로 하는 서브트리에서 가능한 모든 경로 중 최대 합 (각 자식 0 미만이면 안탐) | ||
| current_root = max(max(left, 0) + max(right, 0) + node.val, left_root, right_root) | ||
|
|
||
| return (current, current_root) | ||
|
|
||
| _, ans = calc(root) | ||
|
|
||
| return ans |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석graph-valid-tree/alphaorderly.py"""
시간복잡도: O(n)
공간복잡도: O(n)
먼저 트리의 조건에 맞도록 간선의 갯수가 노드의 갯수 - 1인지 확인하고
Union-Find 알고리즘을 사용하여 간선을 하나씩 추가하며 사이클 여부를 확인한다.
"""
class UnionFind:
def __init__(self, n: int):
self.parent = [-1] * n
self.rank = [0] * n
def find(self, target: int) -> int:
if self.parent[target] == -1:
return target
self.parent[target] = self.find(self.parent[target])
return self.parent[target]
def union(self, a: int, b: int) -> bool:
a = self.find(a)
b = self.find(b)
if a == b:
return False
if self.rank[a] < self.rank[b]:
a, b = b, a
self.parent[b] = a
if self.rank[a] == self.rank[b]:
self.rank[a] += 1
return True
class Solution:
def validTree(self, n: int, edges: List[List[int]]) -> bool:
if len(edges) < n - 1:
return False
u = UnionFind(n)
for a, b in edges:
if not u.union(a, b):
return False
return True
📊 시간/공간 복잡도 분석
피드백: 초기 간선 개수 확인으로 빠르게 거짓 양성을 걸러내고, 각 간선마다 사이클 여부를 체크합니다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| """ | ||
| 시간복잡도: O(n) | ||
| 공간복잡도: O(n) | ||
|
|
||
| 먼저 트리의 조건에 맞도록 간선의 갯수가 노드의 갯수 - 1인지 확인하고 | ||
| Union-Find 알고리즘을 사용하여 간선을 하나씩 추가하며 사이클 여부를 확인한다. | ||
| """ | ||
| class UnionFind: | ||
| def __init__(self, n: int): | ||
| self.parent = [-1] * n | ||
| self.rank = [0] * n | ||
|
|
||
| def find(self, target: int) -> int: | ||
| if self.parent[target] == -1: | ||
| return target | ||
|
|
||
| self.parent[target] = self.find(self.parent[target]) | ||
| return self.parent[target] | ||
|
|
||
| def union(self, a: int, b: int) -> bool: | ||
| a = self.find(a) | ||
| b = self.find(b) | ||
|
|
||
| if a == b: | ||
| return False | ||
|
|
||
| if self.rank[a] < self.rank[b]: | ||
| a, b = b, a | ||
|
|
||
| self.parent[b] = a | ||
| if self.rank[a] == self.rank[b]: | ||
| self.rank[a] += 1 | ||
|
|
||
| return True | ||
|
|
||
|
|
||
| class Solution: | ||
| def validTree(self, n: int, edges: List[List[int]]) -> bool: | ||
|
|
||
| if len(edges) < n - 1: | ||
| return False | ||
|
|
||
| u = UnionFind(n) | ||
|
|
||
| for a, b in edges: | ||
| if not u.union(a, b): | ||
| return False | ||
|
|
||
| return True |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석merge-intervals/alphaorderly.py"""
시간복잡도: O(n log n)
공간복잡도: O(n)
1. 인터벌을 시작시간이 이른 순서대로 정렬한다.
2. 첫 번째 인터벌을 시작시간과 종료시간으로 설정한다.
3. 두 번째 인터벌부터 시작시간이 이전 인터벌의 종료시간보다 작거나 같은 경우 종료시간을 최대값으로 업데이트한다.
4. 그렇지 않은 경우 이전 인터벌을 결과에 추가하고 현재 인터벌을 시작시간과 종료시간으로 설정한다.
5. 마지막 인터벌을 결과에 추가한다.
"""
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort()
N = len(intervals)
schedule = []
start, end = intervals[0]
for i in range(1, N):
event_start, event_end = intervals[i]
if event_start <= end:
end = max(end, event_end)
else:
schedule.append([start, end])
start = event_start
end = event_end
schedule.append([start, end])
return schedule
📊 시간/공간 복잡도 분석
피드백: 정렬과 단일 순회로 병합을 수행하므로 시간 복잡도는 정렬에 의존합니다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| """ | ||
| 시간복잡도: O(n log n) | ||
| 공간복잡도: O(n) | ||
|
|
||
| 1. 인터벌을 시작시간이 이른 순서대로 정렬한다. | ||
| 2. 첫 번째 인터벌을 시작시간과 종료시간으로 설정한다. | ||
| 3. 두 번째 인터벌부터 시작시간이 이전 인터벌의 종료시간보다 작거나 같은 경우 종료시간을 최대값으로 업데이트한다. | ||
| 4. 그렇지 않은 경우 이전 인터벌을 결과에 추가하고 현재 인터벌을 시작시간과 종료시간으로 설정한다. | ||
| 5. 마지막 인터벌을 결과에 추가한다. | ||
| """ | ||
| class Solution: | ||
| def merge(self, intervals: List[List[int]]) -> List[List[int]]: | ||
| intervals.sort() | ||
|
|
||
| N = len(intervals) | ||
| schedule = [] | ||
|
|
||
| start, end = intervals[0] | ||
|
|
||
| for i in range(1, N): | ||
| event_start, event_end = intervals[i] | ||
|
|
||
| if event_start <= end: | ||
| end = max(end, event_end) | ||
| else: | ||
| schedule.append([start, end]) | ||
| start = event_start | ||
| end = event_end | ||
|
|
||
| schedule.append([start, end]) | ||
|
|
||
| return schedule |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석missing-number/alphaorderly.py"""
시간복잡도: O(n)
공간복잡도: O(1)
'target'을 배열의 길이(n)로 설정한 뒤, 0부터 n-1까지의 인덱스와 배열의 모든 값을 xor 연산합니다.
이 과정을 거치면, 배열과 인덱스 모두에 존재하는 값은 xor 연산으로 소거되어 사라집니다(x ^ x = 0).
최종적으로 남는 값이 배열에 존재하지 않는 누락된 숫자가 됩니다.
"""
class Solution:
def missingNumber(self, nums: List[int]) -> int:
target = len(nums)
for i, v in enumerate(nums):
target ^= i ^ v
return target
📊 시간/공간 복잡도 분석
피드백: 배열 원소와 인덱스의 XOR을 이용해 누락된 값을 구합니다. 개선 제안: 현재 구현이 적절해 보입니다.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석missing-number/alphaorderly.py"""
시간복잡도: O(n)
공간복잡도: O(1)
'target'을 배열의 길이(n)로 설정한 뒤, 0부터 n-1까지의 인덱스와 배열의 모든 값을 xor 연산합니다.
이 과정을 거치면, 배열과 인덱스 모두에 존재하는 값은 xor 연산으로 소거되어 사라집니다(x ^ x = 0).
최종적으로 남는 값이 배열에 존재하지 않는 누락된 숫자가 됩니다.
"""
class Solution:
def missingNumber(self, nums: List[int]) -> int:
target = len(nums)
for i, v in enumerate(nums):
target ^= i ^ v
return target
📊 시간/공간 복잡도 분석
피드백: 모든 원소와 인덱스 값을 순회하며 XOR 연산으로 동일한 값은 소거하므로 누락된 값이 최종적으로 남습니다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| """ | ||
| 시간복잡도: O(n) | ||
| 공간복잡도: O(1) | ||
|
|
||
| 'target'을 배열의 길이(n)로 설정한 뒤, 0부터 n-1까지의 인덱스와 배열의 모든 값을 xor 연산합니다. | ||
| 이 과정을 거치면, 배열과 인덱스 모두에 존재하는 값은 xor 연산으로 소거되어 사라집니다(x ^ x = 0). | ||
| 최종적으로 남는 값이 배열에 존재하지 않는 누락된 숫자가 됩니다. | ||
| """ | ||
| class Solution: | ||
| def missingNumber(self, nums: List[int]) -> int: | ||
| target = len(nums) | ||
| for i, v in enumerate(nums): | ||
| target ^= i ^ v | ||
| return target |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석reorder-list/alphaorderly.py"""
시간복잡도: O(n)
공간복잡도: O(1)
1. 토끼와 거북이 포인터를 이용해 연결 리스트의 중간 지점을 찾는다.
2. 중간 지점부터 끝까지의 리스트를 역순으로 뒤집는다.
- 이 과정에서 앞부분과 뒷부분이 분리된다.
3. 앞부분(head)과 뒤집힌 뒷부분을 교차로 연결하여 순서를 재배열한다.
"""
class Solution:
def reorderList(self, head: Optional[ListNode]) -> None:
"""
Do not return anything, modify head in-place instead.
"""
tortoise = hare = head
while hare and hare.next:
tortoise = tortoise.next
hare = hare.next.next
prev, curr = None, tortoise
while curr:
curr.next, prev, curr = prev, curr, curr.next
a, b = head, prev
while b.next:
a.next, a = b, a.next
b.next, b = a, b.next
📊 시간/공간 복잡도 분석
피드백: 두 번의 선형 순회를 통해 in-place 재배열을 달성합니다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| """ | ||
| 시간복잡도: O(n) | ||
| 공간복잡도: O(1) | ||
|
|
||
| 1. 토끼와 거북이 포인터를 이용해 연결 리스트의 중간 지점을 찾는다. | ||
| 2. 중간 지점부터 끝까지의 리스트를 역순으로 뒤집는다. | ||
| - 이 과정에서 앞부분과 뒷부분이 분리된다. | ||
| 3. 앞부분(head)과 뒤집힌 뒷부분을 교차로 연결하여 순서를 재배열한다. | ||
| """ | ||
| class Solution: | ||
| def reorderList(self, head: Optional[ListNode]) -> None: | ||
| """ | ||
| Do not return anything, modify head in-place instead. | ||
| """ | ||
| tortoise = hare = head | ||
|
|
||
| while hare and hare.next: | ||
| tortoise = tortoise.next | ||
| hare = hare.next.next | ||
|
|
||
| prev, curr = None, tortoise | ||
| while curr: | ||
| curr.next, prev, curr = prev, curr, curr.next | ||
|
|
||
| a, b = head, prev | ||
| while b.next: | ||
| a.next, a = b, a.next | ||
| b.next, b = a, b.next |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🏷️ 알고리즘 패턴 분석
binary-tree-maximum-path-sum/alphaorderly.py
📊 시간/공간 복잡도 분석
피드백: 각 노드에서 좌우 서브트리의 정보를 조합해 전체 경로 최대치를 갱신하는 방식으로 트리 전체를 한 번 탐색합니다.
개선 제안: 현재 구현이 적절해 보입니다.