-
-
Notifications
You must be signed in to change notification settings - Fork 195
[moonhyeok] Week 11 #1031
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[moonhyeok] Week 11 #1031
Changes from all commits
4b3bce3
42fc76d
f513c0c
dc07413
d751f6a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* Source: https://www.lintcode.com/problem/178/ | ||
* Solution: 유효한 트리인지 순회하면서 확인하면 되기에 BFS로 구현 | ||
* 시간 복잡도: O(V + E) - 노드와 간선에 한번은 방문 | ||
* 공간 복잡도: O(V + E) - 인접리스트 만큼의 공간 필요 | ||
*/ | ||
function validTree(n: number, edges: number[][]): boolean { | ||
// 간선 개수 체크: 트리는 노드 개수 - 1개의 간선을 가져야 함 | ||
if (edges.length !== n - 1) return false; | ||
|
||
// 인접 리스트 | ||
const adjList: Map<number, number[]> = new Map(); | ||
for (let i = 0; i < n; i++) { | ||
adjList.set(i, []); | ||
} | ||
|
||
// 양방향 그래프 구성 | ||
for (const [u, v] of edges) { | ||
adjList.get(u)!.push(v); | ||
adjList.get(v)!.push(u); | ||
} | ||
|
||
const queue: [number, number][] = [[0, -1]]; // [노드, 부모노드] | ||
const visited: Set<number> = new Set([0]); | ||
|
||
while (queue.length > 0) { | ||
const [node, parent] = queue.shift()!; | ||
|
||
// 모든 이웃 노드 확인 | ||
for (const neighbor of adjList.get(node)!) { | ||
// 부모 노드는 continue | ||
if (neighbor === parent) continue; | ||
|
||
// 이미 방문한 노드를 만나면 사이클 존재 | ||
if (visited.has(neighbor)) return false; | ||
|
||
// 이웃 노드를 큐에 추가하고 방문 표시 | ||
visited.add(neighbor); | ||
queue.push([neighbor, node]); | ||
} | ||
} | ||
|
||
// 모든 노드가 연결되어 있는지 확인 | ||
return visited.size === n; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* Source: https://leetcode.com/problems/maximum-depth-of-binary-tree/ | ||
* 접근법: 최대 깊이만 고려하면 되기에 탐색 알고리즘 중 하나 선택 | ||
* | ||
* 시간복잡도: O(N) - 편향 트리인 경우, 모든 노드(N개) 검색 | ||
* 공간복잡도: O(H) - 트리높이 | ||
* | ||
* 다른 접근법 | ||
* - 재귀를 통해 가독성있는 코드 작성 가능(But, 깊이가 커지면 스택오버플로우가 | ||
*/ | ||
|
||
/** | ||
* Definition for a binary tree node. | ||
* class TreeNode { | ||
* val: number | ||
* left: TreeNode | null | ||
* right: TreeNode | null | ||
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { | ||
* this.val = (val===undefined ? 0 : val) | ||
* this.left = (left===undefined ? null : left) | ||
* this.right = (right===undefined ? null : right) | ||
* } | ||
* } | ||
*/ | ||
|
||
// solution1: array를 stack처럼 사용하면서 DFS구현 | ||
function maxDepth(root: TreeNode | null): number { | ||
if (!root) return 0; | ||
const stack = new Array({ node: root, depth: 1 }); | ||
let maxDepth = 1; | ||
while (stack.length) { | ||
const now = stack.pop(); | ||
if (!now.node?.left && !now.node?.right) { | ||
if (now.depth > maxDepth) maxDepth = now.depth; | ||
continue; | ||
} | ||
stack.push({ node: now.node.left, depth: now.depth + 1 }); | ||
stack.push({ node: now.node.right, depth: now.depth + 1 }); | ||
} | ||
return maxDepth; | ||
} | ||
mike2ox marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// solution2: recursion으로 DFS구현 | ||
function maxDepth(root: TreeNode | null): number { | ||
if (!root) return 0; | ||
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* Source: https://leetcode.com/problems/merge-intervals/ | ||
* 풀이방법: 정령후 첫번째 구간 추가하고 이후 순회하면서 겹치는지 확인 후 병합 or 추가 | ||
* 시간복잡도: O(NlogN) - 정렬에서 NlogN | ||
* 공간복잡도: O(N) - 결과 저장할 공간 | ||
*/ | ||
|
||
function merge(intervals: number[][]): number[][] { | ||
if (intervals.length <= 1) return intervals; | ||
|
||
intervals.sort((a, b) => a[0] - b[0]); | ||
const result: number[][] = [intervals[0]]; | ||
|
||
for (let i = 1; i < intervals.length; i++) { | ||
const current = intervals[i]; | ||
const lastMerged = result[result.length - 1]; | ||
|
||
// 현재 구간의 시작점이 이전 구간의 끝점보다 작거나 같으면 merge | ||
if (current[0] <= lastMerged[1]) { | ||
lastMerged[1] = Math.max(lastMerged[1], current[1]); // 끝점을 두 구간의 끝점 중 더 큰 값으로 업데이트 | ||
} else { | ||
result.push(current); | ||
} | ||
} | ||
|
||
return result; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/** | ||
* Source: https://leetcode.com/problems/reorder-list/ | ||
* 풀이방법: 임시 배열을 사용해서 투포인트 전략으로 풂 | ||
* 시간복잡도: O(n) | ||
* 공간복잡도: O(n) | ||
* | ||
* 추가 풀이 | ||
* - node를 가리키는 두 인자만 사용해서 투포인트 전략이 가능(but, 구현 x) | ||
/ | ||
|
||
/** | ||
* Definition for singly-linked list. | ||
* class ListNode { | ||
* val: number | ||
* next: ListNode | null | ||
* constructor(val?: number, next?: ListNode | null) { | ||
* this.val = (val===undefined ? 0 : val) | ||
* this.next = (next===undefined ? null : next) | ||
* } | ||
* } | ||
*/ | ||
|
||
/** | ||
Do not return anything, modify head in-place instead. | ||
*/ | ||
function reorderList(head: ListNode | null): void { | ||
if (!head || !head.next) return; | ||
|
||
// 1. 모든 노드를 배열에 저장 | ||
const nodes: ListNode[] = []; | ||
let current: ListNode | null = head; | ||
while (current) { | ||
nodes.push(current); | ||
current = current.next; | ||
} | ||
|
||
// 2. 배열의 양끝에서 시작하여 리스트 재구성 | ||
let left = 0; | ||
let right = nodes.length - 1; | ||
|
||
while (left < right) { | ||
// 현재 왼쪽 노드의 다음을 저장 | ||
nodes[left].next = nodes[right]; | ||
left++; | ||
|
||
if (left === right) break; | ||
|
||
// 현재 오른쪽 노드를 다음 왼쪽 노드에 연결 | ||
nodes[right].next = nodes[left]; | ||
right--; | ||
} | ||
|
||
// 마지막 노드의 next를 null로 설정 | ||
nodes[left].next = null; | ||
} | ||
Comment on lines
+26
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 공간복잡도 개선을 위해 slow/fast 포인터를 사용한 방법도 도전해보시면 좋을 것 같습니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mike2ox 님 이번 주도 고생하셨습니다! 주석을 꼼꼼하게 적어주셔서 코드 리뷰가 수월했고, 공부도 많이 되었습니다. 덕분에 "Maximum depth of binary tree"를 반복문으로 접근해볼 수 있었습니다 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
주석을 자세히 적어주셔서, 익숙하지 않은 언어인데도 알고리즘을 이해하기 수월했습니다!