Skip to content

[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

Merged
merged 5 commits into from
Feb 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions graph-valid-tree/mike2ox.ts
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) - 인접리스트 만큼의 공간 필요
*/
Comment on lines +1 to +6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

주석을 자세히 적어주셔서, 익숙하지 않은 언어인데도 알고리즘을 이해하기 수월했습니다!

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;
}
47 changes: 47 additions & 0 deletions maximum-depth-of-binary-tree/mike2ox.ts
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;
}

// solution2: recursion으로 DFS구현
function maxDepth(root: TreeNode | null): number {
if (!root) return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
27 changes: 27 additions & 0 deletions merge-intervals/mike2ox.ts
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;
}
55 changes: 55 additions & 0 deletions reorder-list/mike2ox.ts
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

공간복잡도 개선을 위해 slow/fast 포인터를 사용한 방법도 도전해보시면 좋을 것 같습니다!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mike2ox 님 이번 주도 고생하셨습니다! 주석을 꼼꼼하게 적어주셔서 코드 리뷰가 수월했고, 공부도 많이 되었습니다. 덕분에 "Maximum depth of binary tree"를 반복문으로 접근해볼 수 있었습니다 😄