[musings]
今天写了下 https://leetcode.cn/problems/vvXgSW/description/ ,其实不是特别难,暴力写法也还行但是排序的时间复杂度用堆可以从O(N)压缩到O(log N),但是在用堆写的时候就碰到点问题,js没有内置堆,就手写一个,手写的过程中有几个小问题引发的深思,记录下
Q1:pop和peak的区别?
A: Peak就是游戏里的peak,看一眼最大值,不拿走….
Q2:为什么大顶堆(举例)在pop的时候官方写的版本需要把头尾呼唤然后pop,而不是直接用shift?
A: 如果头尾不互换,直接使用shift,则数组所有位置都会移动,直接破坏了顶堆的特性,那重新排序的时间复杂度就变成O(n),如果把头尾互换,然后删掉尾部,那么只会破坏最头部的最大值顺序,可以只针对顶部元素去做排序,时间复杂度就是O(logn).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| class MaxStack { private stack: number[]; constructor() { this.stack = []; }
push(val: number) { this.stack.push(val); this.sortFromBottom(); }
sortFromBottom() { let currentIndex = this.getLastIndex(); while (true) { let parentIndex = this.getParentIndex(currentIndex); if (currentIndex < 0 || parentIndex < 0 || this.stack[parentIndex] > this.stack[currentIndex]) { break; } else { this.swap(parentIndex, currentIndex); currentIndex = parentIndex; } } }
pop() { this.swap(0, this.getLastIndex()); const popVal = this.stack.pop(); this.sortFromTop(); return popVal; }
sortFromTop() { let currentIndex = 0; while (true) { let leftIndex = this.getLeftIndex(currentIndex); if(leftIndex>this.getLastIndex()) break; let rightIndex = this.getRightIndex(currentIndex); let leftVal = this.stack[leftIndex]; let rightVal = this.stack[rightIndex]; let currentVal = this.stack[currentIndex]; if (currentIndex == this.getLastIndex() || (currentVal > rightVal && currentVal > leftVal)) break; let maxInd = leftVal > rightVal ? leftIndex : rightIndex; if (leftIndex > this.getLastIndex() || rightIndex > this.getLastIndex() || this.stack[maxInd] <= currentVal) break; else { this.swap(maxInd, currentIndex); currentIndex = maxInd; } } }
getLastIndex(): number { return this.stack.length - 1; }
getParentIndex(i: number): number { return Math.floor((i - 1) / 2); }
getLeftIndex(i: number): number { return 2 * i + 1; } getRightIndex(i: number): number { return 2 * i + 2; }
swap(index1: number, index2: number) { let temp = this.stack[index1]; this.stack[index1] = this.stack[index2]; this.stack[index2] = temp; } peak(): number { return this.stack[0]; } print() { return [...this.stack]; } }
let a = new MaxStack(); a.push(4) a.push(14) a.push(8) a.push(16) a.push(24) a.push(9) a.push(11) a.push(15) a.push(34) a.push(26) console.log(a.print());
a.pop(); console.log(a.print());
|