diff --git a/graph-valid-tree/KwonNayeon.py b/graph-valid-tree/KwonNayeon.py new file mode 100644 index 000000000..97c78a50d --- /dev/null +++ b/graph-valid-tree/KwonNayeon.py @@ -0,0 +1,46 @@ +""" +Valid Tree의 조건: +1. 모든 노드가 연결되어 있어야 함 +2. 사이클이 없어야 함 +3. edge의 개수는 n-1개 + +Time Complexity: O(V + E) +- V: 노드의 개수 +- E: edge의 개수 + +Space Complexity: O(V) +- 노드 방문 여부를 저장하는 visited set 사용 + +풀이방법: +1. 기본 조건 체크: edge의 개수는 n-1개 +2. 각 노드별로 연결된 노드들의 정보를 저장 + - 무방향 그래프이므로 양쪽 모두 저장 +3. DFS로 노드 탐색 + - 0번 노드부터 시작해서 연결된 모든 노드를 방문 + - 이미 방문한 노드는 재방문하지 않음 +4. 모든 노드 방문 확인 + - visited의 크기가 n과 같다면 모든 노드가 연결된 것 -> valid tree +""" +def validTree(n, edges): + if len(edges) != n - 1: + return False + + adj = [[] for _ in range(n)] + for a, b in edges: + adj[a].append(b) + adj[b].append(a) + + visited = set() + + def dfs(node): + if node in visited: + return + + visited.add(node) + + for next_node in adj[node]: + dfs(next_node) + + dfs(0) + return len(visited) == n + diff --git a/maximum-depth-of-binary-tree/KwonNayeon.py b/maximum-depth-of-binary-tree/KwonNayeon.py new file mode 100644 index 000000000..a3a36180a --- /dev/null +++ b/maximum-depth-of-binary-tree/KwonNayeon.py @@ -0,0 +1,56 @@ +""" +Constraints: +- The number of nodes in the tree is in the range [0, 10^4]. +- -100 <= Node.val <= 100 + +Time Complexity: O(N) +- N은 트리의 노드 수 +- 모든 노드를 한 번씩 방문하기 때문 + +Space Complexity: O(H) +- H는 트리의 높이 +- 재귀 호출로 인한 호출 스택의 최대 깊이가 트리의 높이와 같음 + +풀이방법: +1. Base case: root가 None인 경우 0을 반환 +2. 재귀를 활용하여 왼쪽과 오른쪽 서브트리 깊이를 각각 계산 +3. 두 서브트리의 깊이 중 최대값에 1을 더해서 반환 (현재 노드의 깊이를 포함) +""" +# 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 + +# Solution 1: 재귀 +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + if root is None: + return 0 + + left_depth = self.maxDepth(root.left) + right_depth = self.maxDepth(root.right) + + return max(left_depth, right_depth) + 1 + +# Solution 2: 반복문 +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + if root is None: + return 0 + + stack = [(root, 1)] + max_depth = 0 + + while stack: + current, depth = stack.pop() + + max_depth = max(max_depth, depth) + + if current.left: + stack.append((current.left, depth + 1)) + if current.right: + stack.append((current.right, depth + 1)) + + return max_depth diff --git a/merge-intervals/KwonNayeon.py b/merge-intervals/KwonNayeon.py new file mode 100644 index 000000000..ffbda221f --- /dev/null +++ b/merge-intervals/KwonNayeon.py @@ -0,0 +1,39 @@ +""" +Constraints: +- 1 <= intervals.length <= 10^4 +- intervals[i].length == 2 +- 0 <= starti <= endi <= 10^4 + +Time Complexity: O(nlogn) +- 정렬에 nlogn, 순회에 n이 필요하므로 전체는 O(nlogn) + +Space Complexity: O(n) +- 최악의 경우 모든 구간이 겹치지 않아 n개의 구간을 저장해야 함 + +풀이방법: +0. intervals를 시작점 기준으로 정렬 +1. merged 배열을 intervals의 첫 번째 구간으로 초기화 +2. intervals의 두 번째 구간부터 순회하면서: + - 현재 구간의 시작점이 merged 배열의 마지막 구간의 끝점보다 작거나 같으면 병합 + - 병합할 때는 끝점을 두 구간의 끝점 중 더 큰 값으로 설정 +3. 현재 구간이 merged의 마지막 구간과 겹치지 않으면 그대로 merged에 추가 +4. 2-3을 반복하여 모든 구간을 처리함 +""" +class Solution: + def merge(self, intervals: List[List[int]]) -> List[List[int]]: + if not intervals: + return [] + + intervals.sort(key=lambda x: x[0]) + + merged = [intervals[0]] + + for interval in intervals[1:]: + if interval[0] <= merged[-1][1]: + merged[-1][1] = max(merged[-1][1], interval[1]) + + else: + merged.append(interval) + + return merged + diff --git a/reorder-list/KwonNayeon.py b/reorder-list/KwonNayeon.py new file mode 100644 index 000000000..21d57255a --- /dev/null +++ b/reorder-list/KwonNayeon.py @@ -0,0 +1,63 @@ +""" +Constraints: +- The number of nodes in the list is in the range [1, 5 * 10^4]. +- 1 <= Node.val <= 1000 + +Time Complexity: O(n) +- 리스트를 한 번씩 순회하면서 알고리즘의 각 단계를 수행함 + +Space Complexity: O(1) +- 정해진 개수의 변수 외에는 추가 공간을 사용하지 않음 + +풀이방법: +1. 중간 지점 찾기 + - slow/fast 포인터를 사용하여 중간 지점 찾기 +2. 뒷부분 뒤집기 + - prev, curr 포인터로 링크드 리스트의 방향 전환 + - next_temp에 다음 노드를 저장한 후 방향 변경 +3. 앞부분과 뒷부분 합치기 + - 두 리스트의 시작점(first, second)부터 시작 + - temp1, temp2에 다음 노드 저장 + - 포인터들을 번갈아가며 연결함 +""" +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def reorderList(self, head: Optional[ListNode]) -> None: + """ + Do not return anything, modify head in-place instead. + """ + # 중간 지점 찾기 + slow = head + fast = head + while fast and fast.next: + slow = slow.next + fast = fast.next.next + + # 뒷부분 뒤집기 + prev = None + curr = slow.next + slow.next = None + while curr: + next_temp = curr.next + curr.next = prev + prev = curr + curr = next_temp + + # 앞부분과 뒷부분 합치기 + first = head + second = prev + while second: + temp1 = first.next + temp2 = second.next + + first.next = second + second.next = temp1 + + first = temp1 + second = temp2 + +