diff --git a/graph-valid-tree/hi-rachel.py b/graph-valid-tree/hi-rachel.py new file mode 100644 index 000000000..da8738d12 --- /dev/null +++ b/graph-valid-tree/hi-rachel.py @@ -0,0 +1,42 @@ +""" +- 정점 개수 n, 간선 배열 edges +- 무방향 그래프 + +트리 조건 +1. 완전히 연결된 그래프여야 함 -> 전체 탐색 가능 +2. 그래프에 순환하는 부분이 없어야 함 + +트리 특성상 항상 e = n - 1, 즉 간선의 수 = 노드의 개수 - 1 + +TC: O(n) +SC: O(n) +""" + +from typing import List + +class Solution: + def validTree(self, n: int, edges: List[List[int]]) -> bool: + graph = [[] for _ in range(n)] + visited = set() + + for a, b in edges: + graph[a].append(b) + graph[b].append(a) + + def has_cycle(node, prev): + # 이미 방문 = 순환 -> 트리 x + if node in visited: + return True + visited.add(node) + for adj in graph[node]: + if adj == prev: + continue + if has_cycle(adj, node): + return True + + return False + + if has_cycle(0, -1): + return False + + return len(visited) == n diff --git a/merge-intervals/hi-rachel.py b/merge-intervals/hi-rachel.py new file mode 100644 index 000000000..4f68e6c86 --- /dev/null +++ b/merge-intervals/hi-rachel.py @@ -0,0 +1,30 @@ +""" +https://leetcode.com/problems/merge-intervals/description/ + +문제 설명: +- 주어진 구간(interval) 리스트에서 겹치는 구간들을 병합(merge)하여 반환합니다. +- 각 구간은 [start, end] 형태입니다. +- 결과는 겹치는 구간이 없는 리스트여야 하며, 정렬된 순서로 반환합니다. + +TC: O(N log N) +- intervals를 정렬하는 데 O(N log N) +- 한 번의 반복으로 병합 처리 → O(N) + +SC: O(N) +- 결과 리스트(output)에 최대 N개의 구간이 저장될 수 있음 +""" + +from typing import List + +class Solution: + def merge(self, intervals: List[List[int]]) -> List[List[int]]: + output = [] + for interval in sorted(intervals): + # output이 비어있거나, 현재 interval이 이전 interval과 겹치지 않으면 그대로 추가 + if not output or output[-1][1] < interval[0]: + output.append(interval) + else: + # 겹치는 경우: 끝나는 부분을 더 긴 쪽으로 병합 + output[-1][1] = max(output[-1][1], interval[1]) + + return output diff --git a/missing-number/hi-rachel.ts b/missing-number/hi-rachel.ts new file mode 100644 index 000000000..628a0560f --- /dev/null +++ b/missing-number/hi-rachel.ts @@ -0,0 +1,29 @@ +/** + * https://leetcode.com/problems/missing-number/ + * + * 문제 설명: + * - 0부터 n까지의 숫자 중 하나가 빠진 길이 n의 배열 nums가 주어집니다. + * - 이 때, 누락된 숫자 하나를 찾아 반환하세요. + * + * 조건: + * - nums.length == n + * - nums의 요소는 고유하며 [0, n] 범위의 정수를 포함합니다. + * + * 풀이 아이디어: + * - 0부터 n까지의 총합을 공식으로 계산한 후, 실제 배열의 총합을 뺍니다. + * 0부터 n까지의 합 공식: + * 0 + 1 + 2 + ... + n = n(n + 1)/2 + * - 빠진 숫자 = 기대 총합 - 실제 총합 + * + * TC: O(n) + * - 배열 순회로 실제 합을 구하는 데 O(n) + * + * SC: O(1) + * - 추가 공간 없이 상수 변수만 사용 + */ + +function missingNumber(nums: number[]): number { + const expectedSum = Math.floor((nums.length * (nums.length + 1)) / 2); + const actualSum = nums.reduce((acc, cur) => acc + cur); + return expectedSum - actualSum; +} diff --git a/reorder-list/hi-rachel.py b/reorder-list/hi-rachel.py new file mode 100644 index 000000000..e3a98b517 --- /dev/null +++ b/reorder-list/hi-rachel.py @@ -0,0 +1,35 @@ +""" +스택에 모든 원소가 저장되어 있다면, 번갈아 가면서, 한 번은 링크드 리스트에서 노드를 얻고, +한 번은 스택에서 원소를 얻는다면, L[0] → L[n - 1] → L[1] → L[n - 2] → L[2] → L[n - 3] → … 순으로 노드에 접근할 수 있을 것 + +TC: O(n) +SC: O(n) +""" + +from typing import Optional + +# 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: + stack = [] + node = head + # 연결 리스트의 모든 노드를 stack에 저장 + while node: + stack.append(node) + node = node.next + + node = dummy = ListNode(-1) + for i in range(len(stack)): + if i % 2: + node.next = stack.pop() # 홀수 인덱스: 뒤에서부터 꺼냄 + else: + node.next = head # 짝수 인덱스: 앞에서부터 가져옴 + head = head.next + node = node.next + node.next = None + return dummy.next