Skip to content

Commit ce836d3

Browse files
authored
Merge pull request #1058 from pmjuu/main
[Lyla] Week 12
2 parents 49315cf + 6f8065e commit ce836d3

File tree

5 files changed

+198
-0
lines changed

5 files changed

+198
-0
lines changed

โ€Žgraph-valid-tree/pmjuu.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'''
2+
๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜๋ฅผ n, ๊ฐ„์„ ์˜ ๊ฐœ์ˆ˜๋ฅผ e ๋ผ๊ณ  ํ• ๋•Œ,
3+
4+
์‹œ๊ฐ„ ๋ณต์žก๋„: O(n + e)
5+
- ๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ๋…ธ๋“œ์™€ ๊ฐ„์„ ์„ ๋ฐฉ๋ฌธํ•˜๋ฏ€๋กœ O(n + e)
6+
7+
๊ณต๊ฐ„ ๋ณต์žก๋„: O(n + e)
8+
- ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ์™€ ๋ฐฉ๋ฌธ ๋ฐฐ์—ด์„ ์ €์žฅํ•˜๋Š” ๋ฐ O(n + e)์˜ ๊ณต๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
9+
'''
10+
from typing import List
11+
12+
class Solution:
13+
def validTree(self, n: int, edges: List[List[int]]) -> bool:
14+
graph = { i: [] for i in range(n) }
15+
for u, v in edges:
16+
graph[u].append(v)
17+
graph[v].append(u)
18+
19+
visited = set()
20+
21+
def hasCycle(node, parent):
22+
if node in visited:
23+
return True
24+
25+
visited.add(node)
26+
27+
for neighbor in graph[node]:
28+
if neighbor == parent:
29+
continue # ๋ถ€๋ชจ ๋…ธ๋“œ๋กœ ๋Œ์•„๊ฐ€์ง€ ์•Š๊ธฐ
30+
if hasCycle(neighbor, node):
31+
return True
32+
33+
return False
34+
35+
# 0๋ฒˆ ๋…ธ๋“œ์—์„œ DFS ์‹œ์ž‘
36+
if hasCycle(0, -1):
37+
return False
38+
39+
# ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ ๋ฐฉ๋ฌธ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ (์—ฐ๊ฒฐ์„ฑ ์ฒดํฌ)
40+
return len(visited) == n
41+
42+
# Example
43+
solution = Solution()
44+
print(solution.validTree(5, [[0, 1], [0, 2], [0, 3], [1, 4]])) # Output: True
45+
print(solution.validTree(5, [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]])) # Output: False
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'''
2+
์‹œ๊ฐ„ ๋ณต์žก๋„: O(n log n)
3+
๊ณต๊ฐ„ ๋ณต์žก๋„: O(1)
4+
'''
5+
from typing import List
6+
7+
8+
class Solution:
9+
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
10+
intervals.sort()
11+
count = 0
12+
iter_intervals = iter(intervals)
13+
prev_end = next(iter_intervals)[1]
14+
15+
for start, end in iter_intervals:
16+
if prev_end > start:
17+
count += 1
18+
prev_end = min(prev_end, end)
19+
else:
20+
prev_end = end
21+
22+
return count
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'''
2+
n: ๋…ธ๋“œ ๊ฐœ์ˆ˜ / e: ๊ฐ„์„  ๊ฐœ์ˆ˜
3+
์‹œ๊ฐ„ ๋ณต์žก๋„: O(n + e)
4+
๊ณต๊ฐ„ ๋ณต์žก๋„: O(n + e)
5+
'''
6+
from typing import List
7+
8+
class Solution:
9+
def count_components(self, n: int, edges: List[List[int]]) -> int:
10+
graph = {i: [] for i in range(n)}
11+
for u, v in edges:
12+
graph[u].append(v)
13+
graph[v].append(u)
14+
15+
visited = set()
16+
def dfs(node):
17+
visited.add(node)
18+
19+
for neighbor in graph[node]:
20+
if neighbor not in visited:
21+
dfs(neighbor)
22+
23+
count = 0
24+
for node in graph:
25+
if node not in visited:
26+
count += 1
27+
dfs(node)
28+
29+
return count
30+
31+
# Test function
32+
def test():
33+
solution = Solution()
34+
test_cases = [
35+
(3, [[0, 1], [0, 2]], 1),
36+
(6, [[0, 1], [1, 2], [2, 3], [4, 5]], 2),
37+
(4, [[0, 1], [2, 3]], 2),
38+
(1, [], 1),
39+
(4, [[0, 1], [2, 3], [1, 2]], 1)
40+
]
41+
42+
for i, (n, edges, expected) in enumerate(test_cases):
43+
result = solution.count_components(n, edges)
44+
print(f"Test case {i+1}: Input: n={n}, edges={edges} -> Output: {result}, Expected: {expected}")
45+
if result != expected:
46+
print(f"# Test case {i+1} failed: expected {expected}, got {result}")
47+
print("\n")
48+
49+
# Run tests
50+
test()
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'''
2+
์‹œ๊ฐ„ ๋ณต์žก๋„: O(n)
3+
๊ณต๊ฐ„ ๋ณต์žก๋„: O(1)
4+
'''
5+
from typing import Optional
6+
7+
# Definition for singly-linked list.
8+
class ListNode:
9+
def __init__(self, val=0, next=None):
10+
self.val = val
11+
self.next = next
12+
13+
# ๋ฆฌ์ŠคํŠธ ์ด ๊ธธ์ด ๊ณ„์‚ฐ
14+
class Solution:
15+
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
16+
# ๋ฆฌ์ŠคํŠธ ๊ธธ์ด ๊ณ„์‚ฐ
17+
length = 1
18+
current = head
19+
while current.next:
20+
length += 1
21+
current = current.next
22+
23+
# ์ œ๊ฑฐํ•  ๋…ธ๋“œ๊ฐ€ ์ฒซ ๋ฒˆ์งธ(head)์ธ ๊ฒฝ์šฐ
24+
if n == length:
25+
return head.next
26+
27+
index = 0
28+
current = head
29+
30+
# ์ œ๊ฑฐ ๋Œ€์ƒ ๋…ธ๋“œ ์ „๊นŒ์ง€ ์ด๋™
31+
for _ in range(length - n - 1):
32+
current = current.next
33+
34+
# ์ œ๊ฑฐ ๋Œ€์ƒ ๋…ธ๋“œ ๊ฑด๋„ˆ๋›ฐ๊ธฐ
35+
current.next = current.next.next
36+
37+
return head
38+
39+
# Two-Pointer
40+
class Solution:
41+
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
42+
first = second = head
43+
44+
# 1. `first`๋ฅผ n ๋งŒํผ ์ด๋™ โ†’ `second`์™€์˜ ๊ฐ„๊ฒฉ ์œ ์ง€
45+
for _ in range(n):
46+
first = first.next
47+
48+
# ์ œ๊ฑฐ ๋Œ€์ƒ์ด ์ฒซ๋ฒˆ์งธ ๋…ธ๋“œ์ธ ๊ฒฝ์šฐ, next ๋ฐ˜ํ™˜
49+
if not first:
50+
return head.next
51+
52+
# 2. `first`๊ฐ€ ๋๊นŒ์ง€ ๊ฐˆ ๋•Œ๊นŒ์ง€ `second`๋„ ํ•จ๊ป˜ ์ด๋™
53+
while first.next:
54+
first = first.next
55+
second = second.next
56+
57+
# 3. `second.next`๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋…ธ๋“œ ์ œ๊ฑฐ
58+
second.next = second.next.next
59+
60+
return head

โ€Žsame-tree/pmjuu.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'''
2+
์‹œ๊ฐ„ ๋ณต์žก๋„: O(n)
3+
๊ณต๊ฐ„ ๋ณต์žก๋„: O(n)
4+
'''
5+
from typing import Optional
6+
7+
# Definition for a binary tree node.
8+
class TreeNode:
9+
def __init__(self, val=0, left=None, right=None):
10+
self.val = val
11+
self.left = left
12+
self.right = right
13+
14+
class Solution:
15+
def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
16+
if not p and not q:
17+
return True
18+
if not p or not q:
19+
return False
20+
21+
return p.val == q.val and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

0 commit comments

Comments
ย (0)