优先队列题目

PriorityQueue - 优先队列:正常⼊、按照优先级出

实现机制

  • Heap (Binary, Binomial, Fibonacci)
  • Binary Search Tree
最小堆实现
class MinHeap {
    constructor(data = []) {
        this.data = data
        // heapify
        if(this.size() > 1) {
            for (let i = 0; i < this.size(); i++) {
                this.bubbleUp(this.data[i])
            }
        }
    }
    
    offer(v) {
        this.data.push(v)
        this.bubbleUp(this.size() - 1)
    }
    
    peek() {
        if (this.size() === 0) return null
        return this.data[0] 
    }

    poll() {
        if(this.size() === 0) return null
        const res = this.data[0]
        const last = this.data.pop()
        if(this.size() > 0) {
            this.data[0] = last
            this.bubbleDown(0)
        }
        return res
    }

    bubbleUp(index) {
        while (index > 0) {
            const parentIndex = (index - 1) >>> 1
            if (this.minus(index, parentIndex) < 0) {
                this.swap(index, parentIndex);
                index = parentIndex
            } else {
                break
            }
        }
    }
    
    bubbleDown(index) {
        const lastIndex = this.size() - 1
        while (1) {
            const l = index * 2 + 1
            const r = index * 2 + 2
            let findIndex = index
            if(l <= lastIndex && this.minus(l, findIndex) < 0) {
                findIndex = l
            }
            if(r <= lastIndex && this.minus(r, findIndex) < 0) {
                findIndex = r
            } 
            if (index !== findIndex) {
                this.swap(index, findIndex)
                index = findIndex
            } else {
                break
            }
        }
    }

    swap(index1, index2) {
        [this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]];
    }

    size() {
        return this.data.length
    }

    minus(a,b) {
        return this.data[a] - this.data[b]
    }
}
703. 数据流中的第 K 大元素

维护一个大小为 k 的最小堆

添加时,堆大小超过 K , 就去掉堆顶元素

最后,保留的都是所有数据流中最大的元素,而堆顶正好是第 K 大的元素

var KthLargest = function(k, nums) {
    this.k = k
    this.heap = new MinHeap()
    for (const x of nums) {
        this.add(x)
    }
};

KthLargest.prototype.add = function(val) {
    this.heap.offer(val)
    if (this.heap.size() > this.k) {
        this.heap.poll()
    }
    return this.heap.peek()
};

class MinHeap {
    constructor(data = []) {
        this.data = data
        // heapify
        if(this.size() > 1) {
            for (let i = 0; i < this.size(); i++) {
                this.bubbleUp(this.data[i])
            }
        }
    }
    
    offer(v) {
        this.data.push(v)
        this.bubbleUp(this.size() - 1)
    }
    
    peek() {
        if (this.size() === 0) return null
        return this.data[0] 
    }

    poll() {
        if(this.size() === 0) return null
        const res = this.data[0]
        const last = this.data.pop()
        if(this.size() > 0) {
            this.data[0] = last
            this.bubbleDown(0)
        }
        return res
    }

    bubbleUp(index) {
        while (index > 0) {
            const parentIndex = (index - 1) >>> 1
            if (this.minus(index, parentIndex) < 0) {
                this.swap(index, parentIndex);
                index = parentIndex
            } else {
                break
            }
        }
    }
    
    bubbleDown(index) {
        const lastIndex = this.size() - 1
        while (1) {
            const l = index * 2 + 1
            const r = index * 2 + 2
            let findIndex = index
            if(l <= lastIndex && this.minus(l, findIndex) < 0) {
                findIndex = l
            }
            if(r <= lastIndex && this.minus(r, findIndex) < 0) {
                findIndex = r
            } 
            if (index !== findIndex) {
                this.swap(index, findIndex)
                index = findIndex
            } else {
                break
            }
        }
    }

    swap(index1, index2) {
        [this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]];
    }

    size() {
        return this.data.length
    }

    minus(a,b) {
        return this.data[a] - this.data[b]
    }
}
239. 滑动窗口最大值

最大堆实现

var maxSlidingWindow = function(nums, k) {
    let n = nums.length;
    let pq = new MaxHeap()
    for (let i = 0; i < k; ++i) {
        pq.offer([nums[i], i]);
    }

    let res = [pq.peek()[0]]
    for (let i = k; i < n; i++) {
        pq.offer([nums[i], i])
        while (pq.peek()[1] <= i - k) {
            pq.poll()
        }
        res.push(pq.peek()[0])
    }
    return res
};

class MaxHeap {
    constructor(data = []) {
        this.data = data
        // heapify
        if(this.size() > 1) {
            for (let i = 0; i < this.size(); i++) {
                this.bubbleUp(this.data[i])
            }
        }
    }

    offer(v) {
        this.data.push(v)
        this.bubbleUp(this.size() - 1)
    }

    peek() {
        if (this.size() === 0) return null
        return this.data[0] 
    }

    poll() {
        if(this.size() === 0) return null
        const res = this.data[0]
        const last = this.data.pop()
        if(this.size() > 0) {
            this.data[0] = last
            this.bubbleDown(0)
        }
        return res
    }

    bubbleUp(index) {
        while (index > 0) {
            const parentIndex = (index - 1) >>> 1
            if (this.minus(index, parentIndex) > 0) {
                this.swap(index, parentIndex);
                index = parentIndex
            } else {
                break
            }
        }
    }

    bubbleDown(index) {
        const lastIndex = this.size() - 1
        while (1) {
            const l = index * 2 + 1
            const r = index * 2 + 2
            let findIndex = index
            if(l <= lastIndex && this.minus(l, findIndex) > 0) {
                findIndex = l
            }
            if(r <= lastIndex && this.minus(r, findIndex) > 0) {
                findIndex = r
            } 
            if (index !== findIndex) {
                this.swap(index, findIndex)
                index = findIndex
            } else {
                break
            }
        }
    }

    swap(index1, index2) {
        [this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]];
    }

    size() {
        return this.data.length
    }

    minus(a,b) {
        return this.data[a][0] - this.data[b][0]
    }
}

双向队列

最右边永远是最大的

var maxSlidingWindow = function(nums, k) {
    const n = nums.length
    const index = []
    for (let i = 0; i < k; i++) {
        while (index.length && nums[i] >= nums[index[index.length - 1]]) {
            // 因为后面比前面大,所以前面的永远不可能会出现,于是直接 pop() ,后面根据 index[0] <= i - k 判断 index 是否在窗口中
            index.pop()
        }
        index.push(i)
    }
    let res = [nums[index[0]]]
    for (let i = k; i < n; i++) {
        while (index.length && nums[i] >= nums[index[index.length - 1]]) {
            index.pop()
        }
        index.push(i)
        // 判断 index[0] 是否在窗口中,如果不再直接 shift 出去
        while (index[0] <= i - k) {
            index.shift()
        }
        res.push(nums[index[0]])
    }
    return res
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值