Skip to content

[soobing] WEEK13 Solutions #1617

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 6 commits into from
Jul 2, 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
131 changes: 131 additions & 0 deletions find-median-from-data-stream/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* 문제 설명
* - 중간 값을 찾는 문제
*
* 아이디어 (👀 어려움..)
* - 최대 힙과 최소 힙을 사용하여 중간 값을 찾는다.
*/
class MinHeap {
heap: number[] = [];
size(): number {
return this.heap.length;
}
peek(): number | null {
return this.heap[0] ?? null;
}
push(val: number) {
this.heap.push(val);
this.bubbleUp(this.size() - 1);
}
pop(): number | null {
if (this.size() === 0) return null;
const top = this.heap[0];
const end = this.heap.pop()!;
if (this.size() > 0) {
this.heap[0] = end;
this.bubbleDown(0);
}
return top;
}
private bubbleUp(idx: number) {
while (idx > 0) {
const parent = Math.floor((idx - 1) / 2);
if (this.heap[parent] <= this.heap[idx]) break;
[this.heap[parent], this.heap[idx]] = [this.heap[idx], this.heap[parent]];
idx = parent;
}
}
private bubbleDown(idx: number) {
const n = this.size();
while (true) {
let left = idx * 2 + 1;
let right = idx * 2 + 2;
let smallest = idx;
if (left < n && this.heap[left] < this.heap[smallest]) smallest = left;
if (right < n && this.heap[right] < this.heap[smallest]) smallest = right;
if (smallest === idx) break;
[this.heap[smallest], this.heap[idx]] = [
this.heap[idx],
this.heap[smallest],
];
idx = smallest;
}
}
}

class MaxHeap {
heap: number[] = [];
size(): number {
return this.heap.length;
}
peek(): number | null {
return this.heap[0] ?? null;
}
push(val: number) {
this.heap.push(val);
this.bubbleUp(this.size() - 1);
}
pop(): number | null {
if (this.size() === 0) return null;
const top = this.heap[0];
const end = this.heap.pop()!;
if (this.size() > 0) {
this.heap[0] = end;
this.bubbleDown(0);
}
return top;
}
private bubbleUp(idx: number) {
while (idx > 0) {
const parent = Math.floor((idx - 1) / 2);
if (this.heap[parent] >= this.heap[idx]) break;
[this.heap[parent], this.heap[idx]] = [this.heap[idx], this.heap[parent]];
idx = parent;
}
}
private bubbleDown(idx: number) {
const n = this.size();
while (true) {
let left = idx * 2 + 1;
let right = idx * 2 + 2;
let largest = idx;
if (left < n && this.heap[left] > this.heap[largest]) largest = left;
if (right < n && this.heap[right] > this.heap[largest]) largest = right;
if (largest === idx) break;
[this.heap[largest], this.heap[idx]] = [
this.heap[idx],
this.heap[largest],
];
idx = largest;
}
}
}

class MedianFinder {
private minH = new MinHeap();
private maxH = new MaxHeap();

addNum(num: number): void {
if (this.maxH.size() === 0 || num <= (this.maxH.peek() ?? num)) {
this.maxH.push(num);
} else {
this.minH.push(num);
}

// Rebalance
if (this.maxH.size() > this.minH.size() + 1) {
this.minH.push(this.maxH.pop()!);
} else if (this.minH.size() > this.maxH.size()) {
this.maxH.push(this.minH.pop()!);
}
}

findMedian(): number {
const total = this.maxH.size() + this.minH.size();
if (total % 2 === 1) {
return this.maxH.peek()!;
} else {
return (this.maxH.peek()! + this.minH.peek()!) / 2;
}
}
}
32 changes: 32 additions & 0 deletions insert-interval/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* 문제 설명
* - 주어진 시간 간격에 대해 회의를 참석할 수 있는지 여부를 반환하는 문제
*
* 아이디어
* 1) 시작 시간을 기준으로 정렬 후, 이전 회의의 종료 시간과 현재 회의의 시작 시간을 비교하여 참석 가능 여부를 판단
*
*/

function insert(intervals: number[][], newInterval: number[]): number[][] {
const result: number[][] = [];
let i = 0;

while (i < intervals.length && newInterval[0] > intervals[i][1]) {
result.push(intervals[i]);
i++;
}

while (i < intervals.length && newInterval[1] >= intervals[i][0]) {
newInterval[0] = Math.min(intervals[i][0], newInterval[0]);
newInterval[1] = Math.max(intervals[i][1], newInterval[1]);
i++;
}
result.push(newInterval);

while (i < intervals.length) {
result.push(intervals[i]);
i++;
}

return result;
}
41 changes: 41 additions & 0 deletions kth-smallest-element-in-a-bst/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* 문제 설명
* - 이진 탐색 트리(BST)가 주어졌을 때, k번째 작은 요소를 찾는 문제
*
* 아이디어
* 1) 중위 순회를 하면서 k번째 작은 요소를 찾는다.
* - 이진 탐색 트리(BST)는 중위 순회(in-order traversal)하면 오름차순으로 정렬된 값을 얻을 수 있다.
*/

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;
}
}

function kthSmallest(root: TreeNode | null, k: number): number {
let result = -1;
let count = 0;

function inOrder(node: TreeNode | null) {
if (!node || result !== -1) return;

inOrder(node.left);
count++;

if (count === k) {
result = node.val;
return;
}

inOrder(node.right);
}

inOrder(root);
return result;
}
32 changes: 32 additions & 0 deletions lowest-common-ancestor-of-a-binary-search-tree/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* 문제 설명
* - 이진 탐색 트리의 두 노드의 최소 공통 조상을 찾는 문제
*
* 아이디어
* 1) 두 노드의 값을 비교하여 최소 공통 조상을 찾는다.
* - 두 노드의 값이 루트 노드보다 작으면 왼쪽 서브트리로 이동
* - 두 노드의 값이 루트 노드보다 크면 오른쪽 서브트리로 이동
* - 두 노드의 값이 루트 노드와 같으면 루트 노드를 반환
*
*/

function lowestCommonAncestor(
root: TreeNode | null,
p: TreeNode | null,
q: TreeNode | null
): TreeNode | null {
if (root === null) return null;
if (p === null || q === null) return null;

while (root !== null) {
if (p.val < root.val && q.val < root.val) {
root = root.left;
} else if (p.val > root.val && q.val > root.val) {
root = root.right;
} else {
return root;
}
}

return root;
}
35 changes: 35 additions & 0 deletions meeting-rooms/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* 문제 설명
* - 주어진 시간 간격에 대해 회의를 참석할 수 있는지 여부를 반환하는 문제
*
* 아이디어
* 1) 시작 시간을 기준으로 정렬 후, 이전 회의의 종료 시간과 현재 회의의 시작 시간을 비교하여 참석 가능 여부를 판단
*
*/

/**
* Definition of Interval:
* class Interval {
* constructor(start, end) {
* this.start = start;
* this.end = end;
* }
* }
*/

class Solution {
/**
* @param {Interval[]} intervals
* @returns {boolean}
*/
canAttendMeetings(intervals) {
intervals = intervals.sort((a, b) => a.start - b.start);

for (let i = 1; i < intervals.length; i++) {
if (intervals[i].start < intervals[i - 1].end) {
return false;
}
}
return true;
}
}