每日一题 -- 堆
313. 超级丑数(补28号)
313. 超级丑数
分析
- 只要建好了堆,只需要暴露出堆和入堆的 api,其他的理解起来还是很简单的
- 先将 prices 都放入最小堆里,堆里的都是丑数
- 每一次出堆一个最小的丑数,同时记录这是第 i 个丑数
- 然后用这个最小的丑数去乘 prices 中的值,去重后(所有出现过的丑数都要去重),加入到小顶堆中
- 重复第四部,一直到出堆的是第 n 个超级丑数即可
var nthSuperUglyNumber = function (n, primes) {
const len = primes.length
const minHeap = new Heap
let map = new Map()
minHeap.heappush(1)
let count = 0
let res = 1
for(let price of primes){
minHeap.heappush(price)
map.set(price, 1)
}
while (count < n) {
res = minHeap.heappop()
for(let price of primes){
const temp = price * res
if (!map.has(temp)) {
minHeap.heappush(temp)
map.set(temp, 1)
}
}
count++
}
return res
};
const Heap = function () {
this.data = []
}
Heap.prototype.heappush = function (val) {
const len = this.data.length
this.data[len] = val
this.up(len)
}
Heap.prototype.heappop = function () {
this.swap(0, this.data.length - 1)
const res = this.data.pop()
this.down(0)
return res
}
Heap.prototype.swap = function (a, b) {
[this.data[a], this.data[b]] = [this.data[b], this.data[a]]
}
Heap.prototype.down = function (index) {
if (index >= this.data.length) return
const left = index * 2 + 1
const right = index * 2 + 2
let target = index
if (left < this.data.length && this.data[left] < this.data[target]) {
target = left
}
if (right < this.data.length && this.data[right] < this.data[target]) {
target = right
}
if (target !== index) {
this.swap(target, index)
this.down(target)
}
}
Heap.prototype.up = function (index) {
if (index === 0) return
const father = (index - 1) >>> 1
if (this.data[index] < this.data[father]) {
this.swap(index, father)
this.up(father)
}
}