diff --git a/find-median-from-data-stream/HoonDongKang.ts b/find-median-from-data-stream/HoonDongKang.ts new file mode 100644 index 000000000..6f7a56c46 --- /dev/null +++ b/find-median-from-data-stream/HoonDongKang.ts @@ -0,0 +1,127 @@ +/** + * [Problem]: [295] Find Median from Data Stream + * (https://leetcode.com/problems/find-median-from-data-stream/description/) + */ +class Heap { + private numbers: number[]; + private compare: (a: number, b: number) => boolean; + + constructor(compare: (a: number, b: number) => boolean) { + this.numbers = []; + this.compare = compare; + } + + private getParentIdx(index: number) { + return Math.floor((index - 1) / 2); + } + + private getLeftChildIdx(index: number) { + return 2 * index + 1; + } + + private getRightChildIdx(index: number) { + return 2 * index + 2; + } + + private swap(index1: number, index2: number): void { + [this.numbers[index1], this.numbers[index2]] = [this.numbers[index2], this.numbers[index1]]; + } + + private heapifyUp(index: number) { + const parentIndex = this.getParentIdx(index); + if (0 <= parentIndex && this.compare(this.numbers[index], this.numbers[parentIndex])) { + this.swap(index, parentIndex); + this.heapifyUp(parentIndex); + } + } + + private heapifyDown(index: number): void { + const leftChildIndex = this.getLeftChildIdx(index); + const rightChildIndex = this.getRightChildIdx(index); + let largestIndex = index; + + if ( + leftChildIndex < this.numbers.length && + this.compare(this.numbers[leftChildIndex], this.numbers[largestIndex]) + ) { + largestIndex = leftChildIndex; + } + + if ( + rightChildIndex < this.numbers.length && + this.compare(this.numbers[rightChildIndex], this.numbers[largestIndex]) + ) { + largestIndex = rightChildIndex; + } + + if (largestIndex !== index) { + this.swap(index, largestIndex); + this.heapifyDown(largestIndex); + } + } + + insert(number: number) { + this.numbers.push(number); + this.heapifyUp(this.numbers.length - 1); + } + + pop() { + if (this.numbers.length === 0) { + return null; + } + + if (this.numbers.length === 1) { + return this.numbers.pop()!; + } + + const root = this.numbers[0]; + this.numbers[0] = this.numbers.pop()!; + this.heapifyDown(0); + + return root; + } + + peek() { + return this.numbers.length > 0 ? this.numbers[0] : null; + } + + size(): number { + return this.numbers.length; + } +} + +class MedianFinder { + private smallHeap: Heap; + private largeHeap: Heap; + + constructor() { + this.smallHeap = new Heap((a, b) => a > b); + this.largeHeap = new Heap((a, b) => a < b); + } + + //시간복잡도 O(log n) + addNum(num: number): void { + this.smallHeap.insert(num); + this.largeHeap.insert(this.smallHeap.pop()!); + + if (this.smallHeap.size() < this.largeHeap.size()) { + this.smallHeap.insert(this.largeHeap.pop()!); + } + } + + //시간복잡도 O(1) + findMedian(): number { + if (this.smallHeap.size() > this.largeHeap.size()) { + return this.smallHeap.peek()!; + } else { + return (this.smallHeap.peek()! + this.largeHeap.peek()!) / 2; + } + } +} + +/** + * Your MedianFinder object will be instantiated and called as such: + * var obj = new MedianFinder() + * obj.addNum(num) + * var param_2 = obj.findMedian() + */ diff --git a/insert-interval/HoonDongKang.ts b/insert-interval/HoonDongKang.ts new file mode 100644 index 000000000..057af667f --- /dev/null +++ b/insert-interval/HoonDongKang.ts @@ -0,0 +1,34 @@ +/** + * [Problem]: [57] Insert Interval + * (https://leetcode.com/problems/insert-interval/) + */ + +//시간복잡도 O(n) +//공간복잡도 O(n) +function insert(intervals: number[][], newInterval: number[]): number[][] { + const result: number[][] = []; + + let idx = 0; + + while (idx < intervals.length && intervals[idx][1] < newInterval[0]) { + result.push(intervals[idx]); + idx++; + } + + while (idx < intervals.length && intervals[idx][0] <= newInterval[1]) { + newInterval = [ + Math.min(intervals[idx][0], newInterval[0]), + Math.max(intervals[idx][1], newInterval[1]), + ]; + idx++; + } + + result.push(newInterval); + + while (idx < intervals.length) { + result.push(intervals[idx]); + idx++; + } + + return result; +} diff --git a/kth-smallest-element-in-a-bst/HoonDongKang.ts b/kth-smallest-element-in-a-bst/HoonDongKang.ts new file mode 100644 index 000000000..85920e75e --- /dev/null +++ b/kth-smallest-element-in-a-bst/HoonDongKang.ts @@ -0,0 +1,34 @@ +/** + * [Problem]: [230] Kth Smallest Element in a BST + * (https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/) + */ + +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 { + //시간복잡도 O(n) + //공간복잡도 O(n) + function inOrderFunc(root: TreeNode | null, k: number): number { + const values: number[] = []; + + function dfs(node: TreeNode | null) { + if (!node) return; + dfs(node.left); + values.push(node.val); + dfs(node.right); + } + + dfs(root); + + return values[k - 1]; + } +} diff --git a/lowest-common-ancestor-of-a-binary-search-tree/HoonDongKang.ts b/lowest-common-ancestor-of-a-binary-search-tree/HoonDongKang.ts new file mode 100644 index 000000000..4b728e7cf --- /dev/null +++ b/lowest-common-ancestor-of-a-binary-search-tree/HoonDongKang.ts @@ -0,0 +1,63 @@ +/** + * [Problem]: [235] Lowest Common Ancestor of a Binary Search Tree + * (https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/description/) + */ + +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 lowestCommonAncestor( + root: TreeNode | null, + p: TreeNode | null, + q: TreeNode | null +): TreeNode | null { + //시간복잡도 O(h) + //공간복잡도 O(h) + function recursiveFunc( + root: TreeNode | null, + p: TreeNode | null, + q: TreeNode | null + ): TreeNode | null { + if (!p || !root || !q) return null; + if (p.val < root.val && q.val < root.val) { + return recursiveFunc(root.left, p, q); + } + if (root.val < p.val && root.val < q.val) { + return recursiveFunc(root.right, p, q); + } + + return root; + } + + //시간복잡도 O(h) + //공간복잡도 O(1) + function loopFunc( + root: TreeNode | null, + p: TreeNode | null, + q: TreeNode | null + ): TreeNode | null { + if (!p || !q || !root) return null; + + let node = root; + + while (node) { + if (p.val < node.val && q.val < node.val) { + node = node?.left!; + } else if (p.val > node.val && q.val > node.val) { + node = node?.right!; + } else { + return node; + } + } + + return null; + } +} diff --git a/meeting-rooms/HoonDongKang.ts b/meeting-rooms/HoonDongKang.ts new file mode 100644 index 000000000..c28f24b67 --- /dev/null +++ b/meeting-rooms/HoonDongKang.ts @@ -0,0 +1,51 @@ +/** + * [Problem]: [920] Meeting Rooms + * (https://www.lintcode.com/problem/920/) + */ + +export class Interval { + start: number; + end: number; + constructor(start: number, end: number) { + this.start = start; + this.end = end; + } +} + +export class Solution { + /** + * @param intervals: an array of meeting time intervals + * @return: if a person could attend all meetings + */ + canAttendMeetings(intervals: Interval[]): boolean { + //시간복잡도 O(n^2) + //공간복잡도 O(1) + function bruteForceFunc(intervals: Interval[]): boolean { + for (let i = 0; i < intervals.length; i++) { + for (let j = i + 1; j < intervals.length; j++) { + const first = intervals[i]; + const second = intervals[j]; + if (first.start < second.end && second.start < first.end) { + return false; + } + } + } + + return true; + } + + //시간복잡도 O(nlogn) + //공간복잡도 O(1) + function sortedFunc(intervals: Interval[]): boolean { + intervals.sort((a, b) => a.start - b.start); + + for (let i = 0; i < intervals.length - 1; i++) { + if (intervals[i].end > intervals[i + 1].start) { + return false; + } + } + + return true; + } + } +}