diff --git a/find-median-from-data-stream/HC-kang.ts b/find-median-from-data-stream/HC-kang.ts new file mode 100644 index 000000000..091263023 --- /dev/null +++ b/find-median-from-data-stream/HC-kang.ts @@ -0,0 +1,164 @@ +/** + * https://leetcode.com/problems/find-median-from-data-stream + * array with binary search + */ +class MedianFinder { + // S.C. O(n) + private nums: number[] = []; + + // T.C. O(n) + addNum(num: number): void { + if (this.nums.length === 0) { + this.nums.push(num); + return; + } else { + this.putNumWithBinarySearch(num); + } + } + + private putNumWithBinarySearch(num: number): void { + let left = 0; + let right = this.nums.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (this.nums[mid] === num) { + this.nums.splice(mid, 0, num); + return; + } else if (this.nums[mid] < num) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + // T.C. O(n) + this.nums.splice(left, 0, num); + } + + // T.C. O(1) + findMedian(): number { + const len = this.nums.length; + + if (len % 2 === 1) { + return this.nums[Math.floor(len / 2)]; + } else { + return (this.nums[len / 2] + this.nums[len / 2 - 1]) / 2; + } + } +} + +/** + * heap... + * TL;DR + */ +class MedianFinder { + // S.C. O(n) + private smallHalf: MaxHeap = new MaxHeap(); + private largeHalf: MinHeap = new MinHeap(); + + // T.C. O(log n) + addNum(num: number): void { + this.smallHalf.push(num); + this.largeHalf.push(this.smallHalf.pop()!); + + if (this.smallHalf.size() < this.largeHalf.size()) { + this.smallHalf.push(this.largeHalf.pop()!); + } + } + + // T.C. O(1) + findMedian(): number { + if (this.smallHalf.size() === this.largeHalf.size()) { + return (this.smallHalf.peek()! + this.largeHalf.peek()!) / 2; + } else { + return this.smallHalf.peek()!; + } + } +} + +class MinHeap { + protected heap: number[] = []; + + push(val: number): void { + this.heap.push(val); + this.heapifyUp(); + } + + pop(): number | undefined { + if (this.heap.length === 0) return undefined; + if (this.heap.length === 1) return this.heap.pop(); + + const result = this.heap[0]; + this.heap[0] = this.heap.pop()!; + this.heapifyDown(); + return result; + } + + peek(): number | undefined { + return this.heap[0]; + } + + size(): number { + return this.heap.length; + } + + private heapifyUp(): void { + let index = this.heap.length - 1; + while (index > 0) { + const parentIndex = Math.floor((index - 1) / 2); + if (this.heap[parentIndex] <= this.heap[index]) break; + + this.swap(parentIndex, index); + index = parentIndex; + } + } + + private heapifyDown(): void { + let index = 0; + while (true) { + let smallest = index; + const leftChild = 2 * index + 1; + const rightChild = 2 * index + 2; + + if ( + leftChild < this.heap.length && + this.heap[leftChild] < this.heap[smallest] + ) { + smallest = leftChild; + } + + if ( + rightChild < this.heap.length && + this.heap[rightChild] < this.heap[smallest] + ) { + smallest = rightChild; + } + + if (smallest === index) break; + + this.swap(index, smallest); + index = smallest; + } + } + + protected swap(i: number, j: number): void { + [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]; + } +} + +class MaxHeap extends MinHeap { + push(val: number): void { + super.push(-val); + } + + pop(): number | undefined { + const val = super.pop(); + return val === undefined ? undefined : -val; + } + + peek(): number | undefined { + const val = super.peek(); + return val === undefined ? undefined : -val; + } +} diff --git a/house-robber/HC-kang.ts b/house-robber/HC-kang.ts new file mode 100644 index 000000000..4e75f45bb --- /dev/null +++ b/house-robber/HC-kang.ts @@ -0,0 +1,15 @@ +/** + * https://leetcode.com/problems/house-robber + * T.C. O(n) + * S.C. O(1) + */ +function rob(nums: number[]): number { + let prev = 0; + let curr = 0; + for (let i = 0; i < nums.length; i++) { + const temp = curr; + curr = Math.max(prev + nums[i], curr); + prev = temp; + } + return curr; +} diff --git a/lowest-common-ancestor-of-a-binary-search-tree/HC-kang.ts b/lowest-common-ancestor-of-a-binary-search-tree/HC-kang.ts new file mode 100644 index 000000000..f6e1c0533 --- /dev/null +++ b/lowest-common-ancestor-of-a-binary-search-tree/HC-kang.ts @@ -0,0 +1,52 @@ +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; + } +} + +/** + * https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/description + * T.C. O(log n) + * S.C. O(log n) + */ +function lowestCommonAncestor( + root: TreeNode | null, + p: TreeNode | null, + q: TreeNode | null +): TreeNode | null { + if (!root) return null; + if (root.val > p!.val && root.val > q!.val) { + return lowestCommonAncestor(root.left, p, q); + } else if (root.val < p!.val && root.val < q!.val) { + return lowestCommonAncestor(root.right, p, q); + } else { + return root; + } +} + +/** + * iterative + * T.C. O(log n) + * S.C. O(1) + */ +function lowestCommonAncestor( + root: TreeNode | null, + p: TreeNode | null, + q: TreeNode | null +): TreeNode | null { + while (root) { + if (root.val > p!.val && root.val > q!.val) { + root = root.left; + } else if (root.val < p!.val && root.val < q!.val) { + root = root.right; + } else { + return root; + } + } + return null; +} diff --git a/meeting-rooms/HC-kang.ts b/meeting-rooms/HC-kang.ts new file mode 100644 index 000000000..9fe1b2a04 --- /dev/null +++ b/meeting-rooms/HC-kang.ts @@ -0,0 +1,12 @@ +/** + * https://leetcode.com/problems/meeting-rooms + * T.C. O(nlogn) + * S.C. O(1) + */ +function canAttendMeetings(intervals: number[][]): boolean { + intervals.sort((a, b) => a[0] - b[0]); + for (let i = 0; i < intervals.length - 1; i++) { + if (intervals[i][1] > intervals[i + 1][0]) return false; + } + return true; +} diff --git a/non-overlapping-intervals/HC-kang.ts b/non-overlapping-intervals/HC-kang.ts new file mode 100644 index 000000000..30bf802c1 --- /dev/null +++ b/non-overlapping-intervals/HC-kang.ts @@ -0,0 +1,29 @@ +/** + * https://leetcode.com/problems/non-overlapping-intervals + * T.C. O(n logn) + * S.C. O(1) + * + * [[1,2],[2,3],[3,4],[1,3]] =(sort by end)=> [[1,2],[2,3],[1,3],[3,4]] + * + * 0 1 2 3 4... + * [=) pass + * [=) pass + * [===) count++ + * ^^^ + * [=) pass + */ +function eraseOverlapIntervals(intervals: number[][]): number { + intervals.sort((a, b) => a[1] - b[1]); + + let count = 0; + let end = -Infinity; + + for (let i = 0; i < intervals.length; i++) { + if (intervals[i][0] < end) { // + count++; + } else { + end = intervals[i][1]; + } + } + return count; +}