Skip to content

Commit 9d58b17

Browse files
authored
Merge pull request #1030 from KwonNayeon/main
[KwonNayeon] Week 11
2 parents cd7eaed + 1f61b43 commit 9d58b17

File tree

4 files changed

+204
-0
lines changed

4 files changed

+204
-0
lines changed

graph-valid-tree/KwonNayeon.py

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""
2+
Valid Tree의 조건:
3+
1. 모든 노드가 연결되어 있어야 함
4+
2. 사이클이 없어야 함
5+
3. edge의 개수는 n-1개
6+
7+
Time Complexity: O(V + E)
8+
- V: 노드의 개수
9+
- E: edge의 개수
10+
11+
Space Complexity: O(V)
12+
- 노드 방문 여부를 저장하는 visited set 사용
13+
14+
풀이방법:
15+
1. 기본 조건 체크: edge의 개수는 n-1개
16+
2. 각 노드별로 연결된 노드들의 정보를 저장
17+
- 무방향 그래프이므로 양쪽 모두 저장
18+
3. DFS로 노드 탐색
19+
- 0번 노드부터 시작해서 연결된 모든 노드를 방문
20+
- 이미 방문한 노드는 재방문하지 않음
21+
4. 모든 노드 방문 확인
22+
- visited의 크기가 n과 같다면 모든 노드가 연결된 것 -> valid tree
23+
"""
24+
def validTree(n, edges):
25+
if len(edges) != n - 1:
26+
return False
27+
28+
adj = [[] for _ in range(n)]
29+
for a, b in edges:
30+
adj[a].append(b)
31+
adj[b].append(a)
32+
33+
visited = set()
34+
35+
def dfs(node):
36+
if node in visited:
37+
return
38+
39+
visited.add(node)
40+
41+
for next_node in adj[node]:
42+
dfs(next_node)
43+
44+
dfs(0)
45+
return len(visited) == n
46+
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""
2+
Constraints:
3+
- The number of nodes in the tree is in the range [0, 10^4].
4+
- -100 <= Node.val <= 100
5+
6+
Time Complexity: O(N)
7+
- N은 트리의 노드 수
8+
- 모든 노드를 한 번씩 방문하기 때문
9+
10+
Space Complexity: O(H)
11+
- H는 트리의 높이
12+
- 재귀 호출로 인한 호출 스택의 최대 깊이가 트리의 높이와 같음
13+
14+
풀이방법:
15+
1. Base case: root가 None인 경우 0을 반환
16+
2. 재귀를 활용하여 왼쪽과 오른쪽 서브트리 깊이를 각각 계산
17+
3. 두 서브트리의 깊이 중 최대값에 1을 더해서 반환 (현재 노드의 깊이를 포함)
18+
"""
19+
# Definition for a binary tree node.
20+
# class TreeNode:
21+
# def __init__(self, val=0, left=None, right=None):
22+
# self.val = val
23+
# self.left = left
24+
# self.right = right
25+
26+
# Solution 1: 재귀
27+
class Solution:
28+
def maxDepth(self, root: Optional[TreeNode]) -> int:
29+
if root is None:
30+
return 0
31+
32+
left_depth = self.maxDepth(root.left)
33+
right_depth = self.maxDepth(root.right)
34+
35+
return max(left_depth, right_depth) + 1
36+
37+
# Solution 2: 반복문
38+
class Solution:
39+
def maxDepth(self, root: Optional[TreeNode]) -> int:
40+
if root is None:
41+
return 0
42+
43+
stack = [(root, 1)]
44+
max_depth = 0
45+
46+
while stack:
47+
current, depth = stack.pop()
48+
49+
max_depth = max(max_depth, depth)
50+
51+
if current.left:
52+
stack.append((current.left, depth + 1))
53+
if current.right:
54+
stack.append((current.right, depth + 1))
55+
56+
return max_depth

merge-intervals/KwonNayeon.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
Constraints:
3+
- 1 <= intervals.length <= 10^4
4+
- intervals[i].length == 2
5+
- 0 <= starti <= endi <= 10^4
6+
7+
Time Complexity: O(nlogn)
8+
- 정렬에 nlogn, 순회에 n이 필요하므로 전체는 O(nlogn)
9+
10+
Space Complexity: O(n)
11+
- 최악의 경우 모든 구간이 겹치지 않아 n개의 구간을 저장해야 함
12+
13+
풀이방법:
14+
0. intervals를 시작점 기준으로 정렬
15+
1. merged 배열을 intervals의 첫 번째 구간으로 초기화
16+
2. intervals의 두 번째 구간부터 순회하면서:
17+
- 현재 구간의 시작점이 merged 배열의 마지막 구간의 끝점보다 작거나 같으면 병합
18+
- 병합할 때는 끝점을 두 구간의 끝점 중 더 큰 값으로 설정
19+
3. 현재 구간이 merged의 마지막 구간과 겹치지 않으면 그대로 merged에 추가
20+
4. 2-3을 반복하여 모든 구간을 처리함
21+
"""
22+
class Solution:
23+
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
24+
if not intervals:
25+
return []
26+
27+
intervals.sort(key=lambda x: x[0])
28+
29+
merged = [intervals[0]]
30+
31+
for interval in intervals[1:]:
32+
if interval[0] <= merged[-1][1]:
33+
merged[-1][1] = max(merged[-1][1], interval[1])
34+
35+
else:
36+
merged.append(interval)
37+
38+
return merged
39+

reorder-list/KwonNayeon.py

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""
2+
Constraints:
3+
- The number of nodes in the list is in the range [1, 5 * 10^4].
4+
- 1 <= Node.val <= 1000
5+
6+
Time Complexity: O(n)
7+
- 리스트를 한 번씩 순회하면서 알고리즘의 각 단계를 수행함
8+
9+
Space Complexity: O(1)
10+
- 정해진 개수의 변수 외에는 추가 공간을 사용하지 않음
11+
12+
풀이방법:
13+
1. 중간 지점 찾기
14+
- slow/fast 포인터를 사용하여 중간 지점 찾기
15+
2. 뒷부분 뒤집기
16+
- prev, curr 포인터로 링크드 리스트의 방향 전환
17+
- next_temp에 다음 노드를 저장한 후 방향 변경
18+
3. 앞부분과 뒷부분 합치기
19+
- 두 리스트의 시작점(first, second)부터 시작
20+
- temp1, temp2에 다음 노드 저장
21+
- 포인터들을 번갈아가며 연결함
22+
"""
23+
# Definition for singly-linked list.
24+
# class ListNode:
25+
# def __init__(self, val=0, next=None):
26+
# self.val = val
27+
# self.next = next
28+
class Solution:
29+
def reorderList(self, head: Optional[ListNode]) -> None:
30+
"""
31+
Do not return anything, modify head in-place instead.
32+
"""
33+
# 중간 지점 찾기
34+
slow = head
35+
fast = head
36+
while fast and fast.next:
37+
slow = slow.next
38+
fast = fast.next.next
39+
40+
# 뒷부분 뒤집기
41+
prev = None
42+
curr = slow.next
43+
slow.next = None
44+
while curr:
45+
next_temp = curr.next
46+
curr.next = prev
47+
prev = curr
48+
curr = next_temp
49+
50+
# 앞부분과 뒷부분 합치기
51+
first = head
52+
second = prev
53+
while second:
54+
temp1 = first.next
55+
temp2 = second.next
56+
57+
first.next = second
58+
second.next = temp1
59+
60+
first = temp1
61+
second = temp2
62+
63+

0 commit comments

Comments
 (0)