问:
- 不停的往一个数组里加数字,如何随时拿到它的中位数
- 打印一个字符串全部子集,包括空字符串
解:
- 创建一个大根堆和小根堆,先往大根堆放一个数,下次再放的数如果比大根堆根节点大就放入小根堆,反之放入大根堆。当两个堆大小相差达到2的时候,就匀一个到少的堆里。这样两个堆的根节点就与中位数有关。
class MedianFinder {
public bigHeap: number[]
public smallHeap: number[]
constructor() {
this.bigHeap = []
this.smallHeap = []
}
addNum(num: number): void {
if (!this.bigHeap.length || num < this.bigHeap[0]) {
this.heapInset(num, this.bigHeap, true)
if (this.bigHeap.length - this.smallHeap.length > 1) {
[this.bigHeap[this.bigHeap.length - 1], this.bigHeap[0]] = [this.bigHeap[0], this.bigHeap[this.bigHeap.length - 1]]
this.heapInset(this.bigHeap.pop(), this.smallHeap, false)
this.heapFy(0, this.bigHeap, true)
}
} else {
this.heapInset(num, this.smallHeap, false)
if (this.smallHeap.length - this.bigHeap.length > 1) {
[this.smallHeap[this.smallHeap.length - 1], this.smallHeap[0]] = [this.smallHeap[0], this.smallHeap[this.smallHeap.length - 1]]
this.heapInset(this.smallHeap.pop(), this.bigHeap, true)
this.heapFy(0, this.smallHeap, false)
}
}
}
findMedian(): number {
if (this.bigHeap.length === this.smallHeap.length) return (this.bigHeap[0] + this.smallHeap[0]) / 2
if (this.bigHeap.length > this.smallHeap.length) return this.bigHeap[0]
return this.smallHeap[0]
}
heapInset(num: number, heap: number[], type: boolean) : void {
heap.push(num)
let curIdx = heap.length - 1
while(type ? (heap[curIdx] > heap[Math.floor((curIdx - 1) / 2)]) : heap[curIdx] < heap[Math.floor((curIdx - 1) / 2)]) {
[heap[curIdx], heap[Math.floor((curIdx - 1) / 2)]] = [heap[Math.floor((curIdx - 1) / 2)], heap[curIdx]];
curIdx = Math.floor((curIdx - 1) / 2)
}
}
heapFy(idx: number, heap: number[], type: boolean) : void {
let leftIdx = 2 * idx + 1
let rightIdx = leftIdx + 1
// 最终下标
let resIdx = idx
// 左不越界,并且比最终下标大,就取左
if (leftIdx < heap.length && (type ? heap[leftIdx] > heap[resIdx] : heap[leftIdx] < heap[resIdx])) resIdx = leftIdx
// 右不越界,并且比最终下标大,就取右
if (rightIdx < heap.length && (type ? heap[rightIdx] > heap[resIdx] : heap[rightIdx] < heap[resIdx])) resIdx = rightIdx;
if (resIdx !== idx) {
[heap[idx], heap[resIdx]] = [heap[resIdx], heap[idx]]
this.heapFy(resIdx, heap, type)
}
}
}
- 声明临时变量tempStr用于保存一次递归完成时最终结果。如果递归到了最后一位,就把这个结果放入结果数组。从0开始递归这个字符串,如果选择要当前字符str[cur],tempStr += str[cur],然后递归下一位。如果选择不要,就把这个字符删掉,继续递归下一位。
function getAllSubset(str) {
let res = []
let tempStr = ''
function getRes(str, idx) {
if (idx === str.length) {
res.push(tempStr)
return
}
// 如果加这个字符
tempStr += str[idx]
getRes(str, idx + 1)
// 如果不加这个字符
tempStr = tempStr.slice(0, -1)
getRes(str, idx + 1)
}
getRes(str, 0)
return res
}