[alphaorderly] WEEK 12 Solutions - #2854
Conversation
There was a problem hiding this comment.
๐ท๏ธ ์๊ณ ๋ฆฌ์ฆ ํจํด ๋ถ์
non-overlapping-intervals/alphaorderly.py
"""
# ์๊ฐ ๋ณต์ก๋: O(n log n)
# ๊ณต๊ฐ ๋ณต์ก๋: O(1)
#
# 1. ์ธํฐ๋ฒ์ ๋์ ์ ๊ธฐ์ค์ผ๋ก ์ค๋ฆ์ฐจ์ ์ ๋ ฌํ๋ค.
# 2. ์ฒซ ๋ฒ์งธ ์ธํฐ๋ฒ์ ๋์ ์ ๊ธฐ์ค์ผ๋ก ์ํํ๋ฉด์,
# ๋ค์ ์ธํฐ๋ฒ์ ์์์ ์ด ํ์ฌ ๋์ ๋ณด๋ค ์์ผ๋ฉด ๊ฒน์น๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ์ฌ ์นด์ดํธ๋ฅผ ์ฆ๊ฐ์ํจ๋ค.
# - ๊ฒน์น๋ฉด(count += 1) ๋์ ์ ๊ทธ๋๋ก ๋๋ค.
# - ๊ฒน์น์ง ์์ผ๋ฉด ๋์ ์ ํ์ฌ ์ธํฐ๋ฒ์ ๋์ ์ผ๋ก ์
๋ฐ์ดํธํ๋ค.
# 3. ๋ง์ง๋ง์ ์นด์ดํธ๋ฅผ ๋ฐํํ๋ค.
#
# ์ ์ต์ ์ธ๊ฐ?
# - ๋์ ์ด ๊ฐ์ฅ ์์ ๊ฒ๋ถํฐ ๋จ๊ฒจ๋๋ฉด ์ดํ๋ก ๋ ๋ง์ ์ธํฐ๋ฒ์ ๋จ๊ธธ ์ ์๋ค.
# - ์ด๋ ์ต๋ํ ๋ง์ ์ธํฐ๋ฒ์ ๋จ๊ธฐ๊ธฐ ์ํด ์ต์ ๊ฐ์์ ์ธํฐ๋ฒ๋ง ์ ๊ฑฐํ๊ฒ ๋๋ ๊ทธ๋ฆฌ๋ ์ ๋ต์ด๋ค.
"""
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals.sort(key=lambda k: k[1])
N = len(intervals)
count = 0
end = intervals[0][1]
for i in range(1, N):
event_start, event_end = intervals[i]
if event_start < end:
count += 1
else:
end = event_end
return count- ํจํด: Greedy
- ์ค๋ช : ์ฃผ์ ์์ด๋์ด๊ฐ ๋์ ์ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ ๋ค, ๊ฒน์น๋ ๊ฒฝ์ฐ๋ฅผ ์ต์ ์ ๊ฑฐ๋ก ํด๊ฒฐํ๋ ๊ทธ๋ฆฌ๋ ์ ๋ต์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค. ๋จผ์ ๋์ ์ด ์์ ์ธํฐ๋ฒ์ ๋จ๊ฒจ๋๊ณ , ๊ฒน์น๋ฉด ์ ๊ฑฐ ์นด์ดํธ๋ฅผ ์ฆ๊ฐ์ํค๋ฉฐ ๋์ ์ ์ ์งํ๊ฑฐ๋ ์ ๋ฐ์ดํธํฉ๋๋ค.
๐ ์๊ฐ/๊ณต๊ฐ ๋ณต์ก๋ ๋ถ์
| ์ ์ ๋ถ์ | ์ค์ ๋ถ์ | ๊ฒฐ๊ณผ | |
|---|---|---|---|
| Time | O(n log n) | O(n log n) | โ |
| Space | O(1) | O(1) | โ |
ํผ๋๋ฐฑ: ์ข ๋ฃ์ ์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ ๋ค ํ ๋ฒ ์ํํ๋ฉฐ ๊ฒน์น๋ ๊ฒฝ์ฐ๋ฅผ ์ธ์ ์ ๊ฑฐ ์๋ฅผ ๊ณ์ฐํ๋ค. ์ถ๊ฐ ๊ณต๊ฐ์ ์์
๊ฐ์ ์ ์: ํ์ฌ ๊ตฌํ์ด ์ ์ ํด ๋ณด์ ๋๋ค.
There was a problem hiding this comment.
๐ท๏ธ ์๊ณ ๋ฆฌ์ฆ ํจํด ๋ถ์
number-of-connected-components-in-an-undirected-graph/alphaorderly.py
"""
# ์๊ฐ ๋ณต์ก๋: O(n) (Union Find ์ฐ์ฐ์ ๊ฒฝ๋ก ์์ถ๊ณผ rank ํ์ฉ์ผ๋ก Amortized O(1))
# ๊ณต๊ฐ ๋ณต์ก๋: O(n)
#
# Union-Find(์ ๋์จ ํ์ธ๋, Disjoint Set Union) ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด ๋ฌด๋ฐฉํฅ ๊ทธ๋ํ์ ์ฐ๊ฒฐ ์์(connected components) ๊ฐ์๋ฅผ ๊ณ์ฐํ๋ค.
#
# ์๊ณ ๋ฆฌ์ฆ ๋จ๊ณ:
# 1. ๊ฐ ๋
ธ๋๋ ์๊ธฐ ์์ ์ ๋ถ๋ชจ๋ก ๊ฐ๋๋ก(parent ๋ฐฐ์ด) ์ด๊ธฐํํ๋ค.
# 2. ํธ๋ฆฌ์ ๊น์ด(๋ญํฌ, rank)๋ฅผ ์ ์ฅํ๋ ๋ฐฐ์ด์ ์ด๊ธฐํํ๋ค.
# 3. ๊ฐ์ ์ ํ๋์ฉ ํ์ธํ๋ฉฐ union ์ฐ์ฐ์ผ๋ก ๋ ๋
ธ๋๋ฅผ ๊ฐ์ ์งํฉ์ผ๋ก ํฉ์น๋ค.
# - ์ด๋ฏธ ๊ฐ์ ์งํฉ์ธ ๊ฒฝ์ฐ์ ์๋ฌด ์์
๋ ํ์ง ์๋๋ค.
# - ์๋ก ๋ค๋ฅธ ์งํฉ์ ํฉ์น๋ฉด, ์ฐ๊ฒฐ ์์ ๊ฐ์๋ฅผ 1 ๊ฐ์์ํจ๋ค.
# 4. ๋ชจ๋ ๊ฐ์ ์ ์ฒ๋ฆฌํ๊ณ ๋จ์ ์ฐ๊ฒฐ ์์ ๊ฐ์(ans)๋ฅผ ๋ฐํํ๋ค.
"""
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 countComponents(self, n: int, edges: List[List[int]]) -> int:
uf = UnionFind(n)
ans = n
for a, b in edges:
if uf.union(a, b):
ans -= 1
return ans- ํจํด: Union Find
- ์ค๋ช : ์ฃผ์ด์ง ์ฝ๋๋ ์๋ก์ ์ฐ๊ฒฐ ์ฌ๋ถ๋ฅผ ๊ด๋ฆฌํ๋ ์ ๋์จ ํ์ธ๋(Disjoint Set Union)๋ก ๊ทธ๋ํ์ ์ฐ๊ฒฐ ์์ ๊ฐ์๋ฅผ ๊ณ์ฐํ๋ค. ๊ฐ์ ์ ํ๋์ฉ ํฉ์น๋ฉฐ ์๋ก ๋ค๋ฅธ ์งํฉ์ด๋ฉด ์ฐ๊ฒฐ ์์๋ฅผ ๊ฐ์์ํค๋ ๋ฐฉ์์ผ๋ก ๊ตฌํ๋๋ค.
๐ ์๊ฐ/๊ณต๊ฐ ๋ณต์ก๋ ๋ถ์
| ๋ณต์ก๋ | |
|---|---|
| Time | O(n + m ฮฑ(n)) |
| Space | O(n) |
ํผ๋๋ฐฑ: ์ด๊ธฐํ์ ํจ๋ฐํธ/๋ญํฌ๋ฅผ ์ฌ์ฉํด ์๋ก ๋ค๋ฅธ ์งํฉ์ ํฉ์น๋ฉฐ ์ฐ๊ฒฐ ์์ ์๋ฅผ ์ ๋ฐ์ดํธํ๋ค
๊ฐ์ ์ ์: ํ์ฌ ๊ตฌํ์ด ์ ์ ํด ๋ณด์ ๋๋ค.
๐ก ํ์ด์ ์๊ฐ/๊ณต๊ฐ ๋ณต์ก๋๋ฅผ ์ฃผ์์ผ๋ก ๋จ๊ฒจ๋ณด์ธ์!
There was a problem hiding this comment.
๐ท๏ธ ์๊ณ ๋ฆฌ์ฆ ํจํด ๋ถ์
remove-nth-node-from-end-of-list/alphaorderly.py
"""
# ์๊ฐ ๋ณต์ก๋: O(n)
# ๊ณต๊ฐ ๋ณต์ก๋: O(1)
#
# ํ ๋ฒ์ ์ํ(one pass)๋ก ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋์์ n๋ฒ์งธ ๋
ธ๋๋ฅผ ์ ๊ฑฐํ๋ ๋ฐฉ๋ฒ:
# 1. dummy ๋
ธ๋๋ฅผ ๋ง๋ค์ด head์ ์์ ์ฐ๊ฒฐํ๋ค.
# 2. forerunner ํฌ์ธํฐ๋ฅผ n์นธ ๋จผ์ ์ด๋์ํจ๋ค.
# 3. forerunner์ lastcomer(์ด๊ธฐ: dummy)๋ฅผ ๊ฐ์ด ํ ์นธ์ฉ ์ด๋ํ๋ฉฐ, forerunner๊ฐ ๋(None)์ ๋๋ฌํ๋ฉด lastcomer๋ ์ ๊ฑฐํ ๋
ธ๋ ๋ฐ๋ก ์์ ์์นํ๊ฒ ๋๋ค.
# 4. lastcomer.next๋ฅผ ๊ฐฑ์ ํ์ฌ n๋ฒ์งธ ๋
ธ๋๋ฅผ ์ ๊ฑฐํ๋ค.
"""
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy = ListNode(0)
dummy.next = head
forerunner = head
lastcomer = dummy
for _ in range(n):
forerunner = forerunner.next
while forerunner:
forerunner = forerunner.next
lastcomer = lastcomer.next
lastcomer.next = lastcomer.next.next
return dummy.next- ํจํด: Two Pointers, Linked List
- ์ค๋ช : ๋ชฉ์ ๋ ธ๋ ์ ๊ฑฐ๋ฅผ ์ํด ๋ ํฌ์ธํฐ๋ฅผ ํ์ฉํ๋ ๋ํ์ ์ธ ํจํด์ผ๋ก, ํ๋๋ฅผ n์นธ ๋จผ์ ์์ง์ด๊ณ ์ดํ ๊ฐ์ด ํ ์นธ์ฉ ์ด๋์ํค๋ฉฐ ํ๊ฒ ๋ ธ๋๋ฅผ ์ฐพ๋๋ค. ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ํ ๋ฒ์ ์ํ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค.
๐ ์๊ฐ/๊ณต๊ฐ ๋ณต์ก๋ ๋ถ์
| ์ ์ ๋ถ์ | ์ค์ ๋ถ์ | ๊ฒฐ๊ณผ | |
|---|---|---|---|
| Time | O(n) | O(n) | โ |
| Space | O(1) | O(1) | โ |
ํผ๋๋ฐฑ: ๋๋ฏธ ํค๋ ๋ฐ ๋ ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํด ์ ๊ฑฐ ์์น๋ฅผ ์ฐพ์ ์ฐ๊ฒฐ์ ๋๋๋ค
๊ฐ์ ์ ์: ํ์ฌ ๊ตฌํ์ด ์ ์ ํด ๋ณด์ ๋๋ค.
There was a problem hiding this comment.
๐ท๏ธ ์๊ณ ๋ฆฌ์ฆ ํจํด ๋ถ์
same-tree/alphaorderly.py
"""
์๊ฐ ๋ณต์ก๋ : O(n)
๊ณต๊ฐ ๋ณต์ก๋ : O(n)
์ฌ๊ท์ ์ผ๋ก ๋ ์ด์ง ํธ๋ฆฌ์ ๋
ธ๋๋ฅผ ๋น๊ตํ๋ฉด์ ๊ฐ์ด ๊ฐ์์ง ํ์ธํ๋ค.
"""
class Solution:
def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
# ๋ ๋
ธ๋๊ฐ ๋๋ค None ์ด๋ฉด True ๋ฅผ ๋ฐํํ๋ค.
if p is q:
return True
# ๋ ๋
ธ๋์ค ํ๋๊ฐ None ์ด๋ฉด False ๋ฅผ ๋ฐํํ๋ค.
if not (p and q):
return False
# ๋๋ค None์ด ์๋๋ผ๋ฉด ๊ฐ์ ๋น๊ตํ๊ณ ์ผ์ชฝ๊ณผ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ๋ ์ฌ๊ท์ ์ผ๋ก ๋น๊ตํ๋ค.
return (
p.val == q.val
and self.isSameTree(p.left, q.left)
and self.isSameTree(p.right, q.right)
)- ํจํด: Binary Search, Depth-First Search, Tre e Pattern
- ์ค๋ช : ์ถ๊ฐ ์ค๋ช : ์ด ์ฝ๋๋ ๋ ํธ๋ฆฌ์ ๋ชจ๋ ๋ ธ๋๋ฅผ ์ฌ๊ท์ ์ผ๋ก ๋น๊ตํ์ฌ ๋์ผ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ค. ๊ฐ ๋ ธ๋์์ ์ข์ฐ ์์์ผ๋ก DFS ๋ฐฉ์์ผ๋ก ์ํํ๋ฉฐ ์กฐ๊ฑด์ ๊ฒ์ฌํ๋ค. ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ค๋ฃฌ๋ค๋ ์ ์์ DFS์ ํน์ฑ์ ๋๋ค.
๐ ์๊ฐ/๊ณต๊ฐ ๋ณต์ก๋ ๋ถ์
| ๋ณต์ก๋ | |
|---|---|
| Time | O(n) |
| Space | O(h) |
ํผ๋๋ฐฑ: ๋ ํธ๋ฆฌ์ ๋์น ์ฌ๋ถ๋ฅผ ๋จ์ ๋น๊ตํ๋ฉฐ ์ข์ฐ ์๋ธํธ๋ฆฌ๊น์ง ์ฌ๊ท์ ์ผ๋ก ํ์ธํ๋ค
๊ฐ์ ์ ์: ํ์ฌ ๊ตฌํ์ด ์ ์ ํด ๋ณด์ ๋๋ค.
๐ก ํ์ด์ ์๊ฐ/๊ณต๊ฐ ๋ณต์ก๋๋ฅผ ์ฃผ์์ผ๋ก ๋จ๊ฒจ๋ณด์ธ์!
๐ alphaorderly ๋์ ํ์ต ํํฉ์ด๋ฒ ์ฃผ ์ ์ถ ๋ฌธ์
๋์ ํ์ต ์์ฝ
๋ฌธ์ ํ์ด ํํฉ
๐ค ์ด ๋๊ธ์ GitHub App์ ํตํด ์๋์ผ๋ก ์์ฑ๋์์ต๋๋ค. ๐ข API ์ฌ์ฉ๋ (gpt-5-nano)
|
There was a problem hiding this comment.
๐ท๏ธ ์๊ณ ๋ฆฌ์ฆ ํจํด ๋ถ์
serialize-and-deserialize-binary-tree/alphaorderly.py
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
"""
# ์๊ฐ ๋ณต์ก๋: O(n)
# ๊ณต๊ฐ ๋ณต์ก๋: O(n)
#
# ์ด ์ฝ๋๋ preorder(์ ์ ์ํ)๋ฅผ ์ด์ฉํด ์ด์ง ํธ๋ฆฌ๋ฅผ ๋ฌธ์์ด๋ก ์ง๋ ฌํํ๊ณ ,
# ๋ค์ preorder ์์๋ก ๋ฌธ์์ด์ ์ญ์ง๋ ฌํํ์ฌ ํธ๋ฆฌ๋ฅผ ๋ณต์ํ๋ค.
#
# 1. serialize ํจ์๋ preorder ์ํ๋ก ํธ๋ฆฌ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํ๋ฉฐ ๊ฐ์ ๋ฌธ์์ด๋ก ์ ์ฅํ๊ณ ,
# None ์๋ฆฌ๋ ํน์๋ฌธ์(*)๋ก ํ๊ธฐํ๋ค.
# 2. deserialize ํจ์๋ preorder ์์์ ๋ฌธ์์ด์ ํ ํญ๋ชฉ์ฉ ์ฝ์ด๊ฐ๋ฉฐ
# *์ด๋ฉด None, ์ซ์๋ฉด ๊ทธ ๊ฐ์ TreeNode๋ฅผ ์ฌ๊ท์ ์ผ๋ก ์์ฑํ๋ค.
"""
class Codec:
def serialize(self, root):
ans = []
def preorder(node: Optional[TreeNode]):
if not node:
ans.append("*")
return
ans.append(str(node.val))
preorder(node.left)
preorder(node.right)
preorder(root)
return ','.join(ans)
def deserialize(self, data):
data = iter(data.split(','))
def preorder() -> TreeNode:
current = next(data)
if current == '*':
return None
node = TreeNode(int(current))
node.left = preorder()
node.right = preorder()
return node
return preorder()
# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# ans = deser.deserialize(ser.serialize(root))- ํจํด: Depth-First Search, Binary Search, Divide and Conquer, Hash Map / Hash Set
- ์ค๋ช : ์ ์ ์ํ ๊ธฐ๋ฐ์ผ๋ก ํธ๋ฆฌ๋ฅผ ๋ฐฉ๋ฌธํ๋ฉฐ ์ฌ๊ท์ ์ผ๋ก ๋ ธ๋๋ฅผ ์์ฑ/๋ณต์ํ๋ฏ๋ก DFS ๊ตฌ์ฑ์ด๋ฉฐ, ์ฌ๊ท์ ํ์์ด ํต์ฌ์ด๋ค. ๋ฌธ์ ๋งฅ๋ฝ์์ ๋ถํ ๋ ์๋ธํธ๋ฆฌ ์ฌ๊ตฌ์ฑ์ Divide and Conquer์ ์ฑ๊ฒฉ๋ ๋ณด์ธ๋ค.
๐ ์๊ฐ/๊ณต๊ฐ ๋ณต์ก๋ ๋ถ์
| ์ ์ ๋ถ์ | ์ค์ ๋ถ์ | ๊ฒฐ๊ณผ | |
|---|---|---|---|
| Time | O(n) | O(n) | โ |
| Space | O(n) | O(n) | โ |
ํผ๋๋ฐฑ: None ๋ ธ๋๋ '*'๋ก ํ๊ธฐํ์ฌ ๊ตฌ์กฐ๋ฅผ ๋ณด์กดํ๋ค
๊ฐ์ ์ ์: ํ์ฌ ๊ตฌํ์ด ์ ์ ํด ๋ณด์ ๋๋ค.
๋ต์ ์ ์ถ ๋ฌธ์
์์ฑ์ ์ฒดํฌ ๋ฆฌ์คํธ
In Review๋ก ์ค์ ํด์ฃผ์ธ์.๊ฒํ ์ ์ฒดํฌ ๋ฆฌ์คํธ
Important
๋ณธ์ธ ๋ต์ ์ ์ถ ๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ ๋ถ PR ํ๋ ์ด์์ ๋ฐ๋์ ๊ฒํ ๋ฅผ ํด์ฃผ์ ์ผ ํฉ๋๋ค!