Skip to content

Commit 5e8b06e

Browse files
authored
Merge pull request #1587 from soobing/week12
[soobing] WEEK12 Solutions
2 parents 6b13bd1 + c59802d commit 5e8b06e

File tree

5 files changed

+320
-0
lines changed

5 files changed

+320
-0
lines changed

non-overlapping-intervals/soobing.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* 문제 설명
3+
* - 겹치지 않는 최대한 많은 구간을 선택하는 문제 (그러기 위해서는 몇개를 제거해야하는지)
4+
*
5+
* 아이디어
6+
* 1) 그리디 알고리즘
7+
* - 최대한 많은 구간 선택을 위해서는 끝나는 시간을 기준으로 정렬
8+
* - 순회 하면서 다음 시작 시간이 현재 끝나는 시간보다 크거나 같으면 카운트 증가
9+
*/
10+
function eraseOverlapIntervals(intervals: number[][]): number {
11+
if (intervals.length === 0) return 0;
12+
13+
intervals.sort((a, b) => a[1] - b[1]);
14+
15+
let count = 1;
16+
let end = intervals[0][1];
17+
18+
for (let i = 1; i < intervals.length; i++) {
19+
if (intervals[i][0] >= end) {
20+
count++;
21+
end = intervals[i][1];
22+
}
23+
}
24+
return intervals.length - count;
25+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* 문제 설명
3+
* - 무방향 그래프에서 연결된 노드의 갯수를 구하는 문제
4+
*
5+
* 아이디어
6+
* 1) 그래프 생성 + DFS로 탐색
7+
* 2) Union-Find -> ⚠️ 다음에 이걸로 해보기
8+
* - 모든 노드를 자기 자신을 부모로 초기화
9+
* - 각 edge에 대해 union 연산 수행
10+
* - 최종적으로 남아있는 루트(대표 노드)의 개수가 연결 요소 수
11+
*/
12+
function countComponents(n: number, edges: number[][]): number {
13+
const graph: Record<number, number[]> = {};
14+
for (let i = 0; i < n; i++) graph[i] = [];
15+
16+
for (const [a, b] of edges) {
17+
graph[a].push(b);
18+
graph[b].push(a);
19+
}
20+
21+
const visited = new Set<number>();
22+
let count = 0;
23+
24+
const dfs = (node: number) => {
25+
visited.add(node);
26+
for (const neighbor of graph[node]) {
27+
if (!visited.has(neighbor)) {
28+
dfs(neighbor);
29+
}
30+
}
31+
};
32+
33+
for (let i = 0; i < n; i++) {
34+
if (!visited.has(i)) {
35+
dfs(i);
36+
count++;
37+
}
38+
}
39+
40+
return count;
41+
}
42+
43+
function countComponents2(n: number, edges: number[][]): number {
44+
const parent = Array(n)
45+
.fill(0)
46+
.map((_, i) => i);
47+
48+
// find 함수 (경로 압축 포함)
49+
const find = (x: number): number => {
50+
if (parent[x] !== x) {
51+
parent[x] = find(parent[x]);
52+
}
53+
return parent[x];
54+
};
55+
56+
// union 함수 (다른 집합이면 병합하고 true 반환)
57+
const union = (x: number, y: number): boolean => {
58+
const rootX = find(x);
59+
const rootY = find(y);
60+
if (rootX === rootY) return false;
61+
parent[rootX] = rootY;
62+
return true;
63+
};
64+
65+
let count = n;
66+
67+
for (const [a, b] of edges) {
68+
if (union(a, b)) {
69+
count--; // 서로 다른 집합을 연결했으므로 연결 요소 수 줄임
70+
}
71+
}
72+
73+
return count;
74+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* 문제 설명
3+
* - 연결 리스트의 "끝"에서 n번째 노드를 제거하는 문제
4+
*
5+
* 아이디어
6+
* 1) 투 포인터 기법 ⚠️
7+
* - fast, slow 포인터간의 간격을 n + 1만큼 벌리면 fast 포인터가 끝에 도달했을 경우, slow 포인터를 활용하여 제거 가능하다.
8+
* - 주의할점은 노드가 하나만 존재하는 케이스를 대응하기 위해 더미 노드를 사용한다.
9+
*
10+
*/
11+
/**
12+
* Definition for singly-linked list.
13+
* class ListNode {
14+
* val: number
15+
* next: ListNode | null
16+
* constructor(val?: number, next?: ListNode | null) {
17+
* this.val = (val===undefined ? 0 : val)
18+
* this.next = (next===undefined ? null : next)
19+
* }
20+
* }
21+
*/
22+
23+
class ListNode {
24+
val: number;
25+
next: ListNode | null;
26+
constructor(val?: number, next?: ListNode | null) {
27+
this.val = val === undefined ? 0 : val;
28+
this.next = next === undefined ? null : next;
29+
}
30+
}
31+
32+
function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
33+
let dummy = new ListNode(0, head);
34+
let fast: ListNode | null = dummy;
35+
let slow: ListNode | null = dummy;
36+
37+
for (let i = 0; i < n + 1; i++) {
38+
fast = fast!.next;
39+
}
40+
41+
while (fast) {
42+
fast = fast.next;
43+
slow = slow!.next;
44+
}
45+
46+
slow!.next = slow!.next!.next;
47+
return dummy.next;
48+
}

same-tree/soobing.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* 문제 설명
3+
* - 두 이진 트리가 같은지 확인하는 문제
4+
*
5+
* 아이디어
6+
* 1) 트리 탐색 (BFS, DFS)을 하면서 비교한다.
7+
*/
8+
9+
class TreeNode {
10+
val: number;
11+
left: TreeNode | null;
12+
right: TreeNode | null;
13+
14+
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
15+
this.val = val === undefined ? 0 : val;
16+
this.left = left === undefined ? null : left;
17+
this.right = right === undefined ? null : right;
18+
}
19+
}
20+
21+
function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
22+
if (!p && !q) return true;
23+
if (!p || !q) return false;
24+
if (p.val !== q.val) return false;
25+
26+
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
27+
}
28+
29+
function isSameTreeBFS(p: TreeNode | null, q: TreeNode | null): boolean {
30+
const queue1: (TreeNode | null)[] = [p];
31+
const queue2: (TreeNode | null)[] = [q];
32+
33+
while (queue1.length > 0 && queue2.length > 0) {
34+
const node1 = queue1.shift();
35+
const node2 = queue2.shift();
36+
37+
if (!node1 && !node2) continue;
38+
if (!node1 || !node2) return false;
39+
if (node1.val !== node2.val) return false;
40+
41+
queue1.push(node1.left);
42+
queue1.push(node1.right);
43+
queue2.push(node2.left);
44+
queue2.push(node2.right);
45+
}
46+
47+
return queue1.length === queue2.length;
48+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* 문제 설명
3+
* - 이진 트리를 직렬화/역직렬화 하는 문제
4+
*
5+
* 아이디어
6+
* 1) 트리를 순회하면서 value값만 담는다.
7+
* - DFS, BFS 둘 다 가능
8+
* - DFS는 재귀 기반이라 코드가 간결하고, BFS 보다 메모리 사용량은 적지만, 깊은 트리에서는 스택 오버플로우가 발생할 수 있다.
9+
* - 반면에 BFS는 큐를 많이 사용해서 폭이 넓은 트리에서 비효율적일 수 있지만,
10+
*/
11+
12+
class TreeNode {
13+
val: number;
14+
left: TreeNode | null;
15+
right: TreeNode | null;
16+
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
17+
this.val = val === undefined ? 0 : val;
18+
this.left = left === undefined ? null : left;
19+
this.right = right === undefined ? null : right;
20+
}
21+
}
22+
23+
/*
24+
* Encodes a tree to a single string.
25+
*/
26+
function serialize(root: TreeNode | null): string {
27+
const result: string[] = [];
28+
29+
const dfs = (node: TreeNode | null) => {
30+
if (node === null) {
31+
result.push("null");
32+
return;
33+
}
34+
35+
result.push(node.val.toString());
36+
dfs(node.left);
37+
dfs(node.right);
38+
};
39+
40+
dfs(root);
41+
return result.join(",");
42+
}
43+
44+
/*
45+
* Decodes your encoded data to tree.
46+
*/
47+
function deserialize(data: string): TreeNode | null {
48+
const values = data.split(",");
49+
let i = 0;
50+
const dfs = () => {
51+
if (values[i] === "null") {
52+
i++;
53+
return null;
54+
}
55+
56+
const node = new TreeNode(Number(values[i]));
57+
i++;
58+
node.left = dfs();
59+
node.right = dfs();
60+
return node;
61+
};
62+
return dfs();
63+
}
64+
65+
/**
66+
* Your functions will be called as such:
67+
* deserialize(serialize(root));
68+
*/
69+
70+
/*
71+
* Encodes a tree to a single string.
72+
*/
73+
function serializeBFS(root: TreeNode | null): string {
74+
if (!root) return "null";
75+
76+
const queue: (TreeNode | null)[] = [root];
77+
const result: string[] = [];
78+
79+
while (queue.length > 0) {
80+
const node = queue.shift();
81+
if (node) {
82+
result.push(node.val.toString());
83+
queue.push(node.left);
84+
queue.push(node.right);
85+
} else {
86+
result.push("null");
87+
}
88+
}
89+
return result.join(",");
90+
}
91+
92+
/*
93+
* Decodes your encoded data to tree.
94+
*/
95+
function deserializeBFS(data: string): TreeNode | null {
96+
const values = data.split(",");
97+
98+
if (values[0] === "null") return null;
99+
100+
const root = new TreeNode(Number(values[0]));
101+
let i = 1;
102+
const queue: (TreeNode | null)[] = [root];
103+
104+
while (queue.length > 0 && i < values.length) {
105+
const current = queue.shift();
106+
const left = values[i++];
107+
const right = values[i++];
108+
109+
if (left !== "null") {
110+
current!.left = new TreeNode(Number(left));
111+
queue.push(current!.left);
112+
}
113+
114+
if (right !== "null") {
115+
current!.right = new TreeNode(Number(right));
116+
queue.push(current!.right);
117+
}
118+
}
119+
return root;
120+
}
121+
122+
/**
123+
* Your functions will be called as such:
124+
* deserialize(serialize(root));
125+
*/

0 commit comments

Comments
 (0)