diff --git a/ContainerWithMostWater.py b/ContainerWithMostWater.py new file mode 100644 index 0000000..aa4a803 --- /dev/null +++ b/ContainerWithMostWater.py @@ -0,0 +1,21 @@ +class Solution: + def maxArea(self, h: List[int]) -> int: + # Here, instead of trying to do N^2 brute force, we go smart way + # We search for the highest peak from side were we have lowest peak. + # If for example left peak is higher than right, we want to find same hight or more peak on right, so we have possibility to beat our result. + # When we search the higher peak, we hope that length decreasing (r - l) if gonna be beaten by peak growth + # (h[l] or h[r] will be much greater than lMax or rMax respectivly) + res = 0 + l, r = 0, len(h) - 1 + lMax = rMax = 0 + while l < r: + lMax = max(h[l], lMax) + rMax = max(h[r], rMax) + res = max(min(h[l],h[r]) * (r - l), res) + if rMax > lMax: + l += 1 + else: + r -= 1 + + return res + # To be honest, I just got that solution in the head somehow... diff --git a/MaxHeap.js b/MaxHeap.js new file mode 100644 index 0000000..41fedf1 --- /dev/null +++ b/MaxHeap.js @@ -0,0 +1,68 @@ +export default class MaxHeap { + #heap; + + #parent = (i) => Math.floor((i - 2) / 2); + #left = (i) => i * 2 + 1; + #right = (i) => i * 2 + 2; + + constructor(heap = []) { + this.#heap = heap; + heap.reduceRight((_, __, i) => this.#heapifyBottom(i)); + } + + pop() { + const heap = this.#heap, + result = heap[0], + last = heap.pop(); + if (heap.length) { + heap[0] = last; + this.#heapifyBottom(0); + } + return result; + } + + push(num) { + this.#heap.push(num); + this.#heapifyTop(this.#heap.length - 1); + } + + #heapifyBottom = (i) => { + const heap = this.#heap; + + while (1) { + const l = this.#left(i), + r = this.#right(i); + if (heap[r] > heap[i] && !(heap[r] < heap[l])) { + [heap[i], heap[r]] = [heap[r], heap[i]]; + i = r; + } else if (heap[l] > heap[i] && !(heap[l] < heap[r])) { + [heap[i], heap[l]] = [heap[l], heap[i]]; + i = l; + } else { + break; + } + } + }; + + #heapifyTop = (i) => { + const heap = this.#heap; + + while (0 < i) { + const p = this.#parent(i); + if (0 <= p && heap[i] > heap[p]) { + [heap[p], heap[i]] = [heap[i], heap[p]]; + } + i = p; + } + }; + + get [Symbol.toStringTag]() { + return 'Heap'; + } + get [Symbol.iterator]() { + return this.#heap[Symbol.iterator].bind(this.#heap); + } + get heap() { + return [...this.#heap]; + } +} diff --git a/MinHeap.js b/MinHeap.js new file mode 100644 index 0000000..0f3495f --- /dev/null +++ b/MinHeap.js @@ -0,0 +1,68 @@ +export default class MinHeap { + #heap; + + #parent = (i) => Math.floor((i - 2) / 2); + #left = (i) => i * 2 + 1; + #right = (i) => i * 2 + 2; + + constructor(heap = []) { + this.#heap = heap; + heap.reduceRight((_, __, i) => this.#heapifyBottom(i)); + } + + pop() { + const heap = this.#heap, + result = heap[0], + last = heap.pop(); + if (heap.length) { + heap[0] = last; + this.#heapifyBottom(0); + } + return result; + } + + push(num) { + this.#heap.push(num); + this.#heapifyTop(this.#heap.length - 1); + } + + #heapifyBottom = (i) => { + const heap = this.#heap; + + while (1) { + const l = this.#left(i), + r = this.#right(i); + if (heap[r] < heap[i] && !(heap[r] > heap[l])) { + [heap[i], heap[r]] = [heap[r], heap[i]]; + i = r; + } else if (heap[l] < heap[i] && !(heap[l] > heap[r])) { + [heap[i], heap[l]] = [heap[l], heap[i]]; + i = l; + } else { + break; + } + } + }; + + #heapifyTop = (i) => { + const heap = this.#heap; + + while (0 < i) { + const p = this.#parent(i); + if (0 <= p && heap[i] < heap[p]) { + [heap[p], heap[i]] = [heap[i], heap[p]]; + } + i = p; + } + }; + + get [Symbol.toStringTag]() { + return 'Heap'; + } + get [Symbol.iterator]() { + return this.#heap[Symbol.iterator].bind(this.#heap); + } + get heap() { + return [...this.#heap]; + } +} diff --git a/MinHeap.ts b/MinHeap.ts new file mode 100644 index 0000000..7dad94f --- /dev/null +++ b/MinHeap.ts @@ -0,0 +1,68 @@ +export default class MinHeap { + #heap: number[]; + + #parent = (i: number): number => Math.floor((i - 2) / 2); + #left = (i: number): number => i * 2 + 1; + #right = (i: number): number => i * 2 + 2; + + constructor(heap: number[] = []) { + this.#heap = heap; + heap.reduceRight((_, __, i: number): any => this.#heapifyBottom(i)); + } + + pop(): number { + const heap = this.#heap, + result = heap[0], + last = heap.pop(); + if (heap.length) { + heap[0] = last; + this.#heapifyBottom(0); + } + return result; + } + + push(num: number): void { + this.#heap.push(num); + this.#heapifyTop(this.#heap.length - 1); + } + + #heapifyBottom = (i: number): void => { + const heap = this.#heap; + + while (1) { + const l = this.#left(i), + r = this.#right(i); + if (heap[r] < heap[i] && !(heap[r] > heap[l])) { + [heap[i], heap[r]] = [heap[r], heap[i]]; + i = r; + } else if (heap[l] < heap[i] && !(heap[l] > heap[r])) { + [heap[i], heap[l]] = [heap[l], heap[i]]; + i = l; + } else { + break; + } + } + }; + + #heapifyTop = (i: number): void => { + const heap = this.#heap; + + while (0 < i) { + const p = this.#parent(i); + if (0 <= p && heap[i] < heap[p]) { + [heap[p], heap[i]] = [heap[i], heap[p]]; + } + i = p; + } + }; + + get [Symbol.toStringTag](): string { + return 'Heap'; + } + get [Symbol.iterator](): () => IterableIterator { + return this.#heap[Symbol.iterator].bind(this.#heap); + } + get heap(): number[] { + return [...this.#heap]; + } +} diff --git a/test.ts b/test.ts new file mode 100644 index 0000000..68a6c34 --- /dev/null +++ b/test.ts @@ -0,0 +1,10 @@ +// @ts-ignore +import Heap from './heap.ts'; +const h = new Heap([14, 12, 6, 23, 11, 19, 17, 3, 4]); +console.log(h.heap); +console.log(h.pop()); +console.log(h.pop()); +console.log(h.pop()); +h.push(7); +console.log(h.pop()); +console.log(h.pop());