前端就该用 JS 刷算法28(待补)

415 阅读1分钟

每日一题 -- 堆

313. 超级丑数

313. 超级丑数

分析

  1. 就是动态的从小顶堆中取最小值
  2. 每次都将小顶堆出来的值和 primes 相乘,去重后加入到堆中,整理
  3. 最后取了 n-1 次之后,就得到了第 n 个超级丑数

but:超时了


// https://leetcode-cn.com/problems/super-ugly-number/
// 313. 超级丑数

/**
 * @分析 -- 超时了
 * 
 */
var nthSuperUglyNumber = function (n, primes) {
    const len = primes.length
    // 构建初始化的小顶堆
    const minHeap = new Heap(len)
    let map = new Map()
    let count = 1
    let res = 1
    for (let i = 0; i < len; i++) {
        map.set(primes[i], 1)
        minHeap.data[i + 1] = primes[i]
        minHeap.up(i)
    }
    while (count < n) {
        res = minHeap.poll()
        for (let i = 0; i < len; i++) {
            const temp = primes[i] * res
            if (!map.has(temp)) {
                map.set(temp, 1)
                minHeap.data[minHeap.data.length] = temp
                for (let j = minHeap.data.length; j > 0; j--) {
                    minHeap.up(j)
                }
            }
        }
        count++
    }

    // 第 n 次循环的时候已经跳出,所以 res 取到的是 n-1 次循环的时的值,
    // 但是由于第一个值是1,所以 res 就是第 n 个超级丑数
    return res
};

// 构建小顶堆
const Heap = function (n) {
    this.data = new Array(n + 1)
}

Heap.prototype.swap = function (a, b) {
    [this.data[a], this.data[b]] = [this.data[b], this.data[a]]
}

Heap.prototype.poll = function () {
    // 堆顶和最后一个值交换
    this.swap(1, this.data.length - 1)
    // 删除掉堆顶的值
    const res = this.data.pop()
    // 自上而下的整理
    this.down(1)
    return res
}

Heap.prototype.down = function (index) {
    if (index >= this.data.length) return
    const left = index * 2
    const right = index * 2 + 1
    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 === 1) return
    const father = index >>> 1
    if (this.data[index] < this.data[father]) {
        this.swap(index, father)
        this.up(father)
    }
}