基于前面的优先队列的构建
[LeetCode.215]数组中第K大个元素
解析
- 第K大个元素,我们可以定义一个小顶堆, 因为最小值是跟节点,每次都可以pop出去
- 保持顶堆元素大小是K, 当小于K的时候 逐个push, 当只有大于我们的根顶元素值的时候再push,然后把 根顶元素pop出去, 最终我们的根顶就是第K大
// 定义小顶堆的值比较方法
function compare(a, b) {
return a < b
}
function findKthLargest(nums, k) {
const heap = new Heap(compare)
for (let i = 0; i < nums.length; i++) {
if(heap.size() < k || heap.top() < nums[i]) {
heap.push(nums[i])
if (heap.size() > k) {
heap.pop()
}
}
}
return heap.top()
}
【Leetcode.offer40】最小的K个数
解析
- 因为是取最小的K个数,所以定义大顶堆,先把沾满K个元素,小于根顶元素的时候再替换
var getLeastNumbers = function(arr, k) {
// 默认是a > b 大顶堆
const heap = new Heap()
for (let i = 0; i < arr.length; i++) {
if (heap.size() < k || arr[i] < heap.top()) {
heap.push(arr[i])
if (heap.size() > k) {
heap.pop()
}
}
}
return heap.data
};
【Leetcode。1046】最后一块石头的重量
题目
有一堆石头,每块石头的重量都是正整数。
每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎; 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。 最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。
解析
- 更具题意需要一个大顶堆来去消减石头
- 每次取出两块石头对比即 pop() 两次
- 终止配石头的条件是 剩余一块时候或者没有石头的时候
var lastStoneWeight = function(stones) {
// 创建一个大顶堆
const heap = new Heap()
// 把石头添加到堆里
for (let i = 0; i < stones.length;i++) {
heap.push(stones[i])
}
// 配石头的边界条件
while(heap.size() > 1) {
const f = heap.top()
heap.pop()
const s = heap.top()
heap.pop()
// 如果碰撞后剩余石头则在加入堆中
if (f - s > 0) {
heap.push(f - s)
}
}
// return 出最后块石头的重量或者空的时候0
return heap.size() ? heap.top() : 0
}
【Leetcode.703数据流中第K大元素】
题
设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。
请实现 KthLargest 类:
KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。 int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。
解析
- 和数组中第K大元素差不离, 构建小顶堆, push的条件也是一样
// 小顶堆的比较方法
function compare(a, b) {
return a < b
}
var KthLargest = function(k, nums) {
this.heap = new Heap(compare)
this.k = k
for (let i = 0; i < nums.length; i++) {
this.add(nums[i])
}
};
KthLargest.prototype.add = function(val) {
if (this.heap.size() < this.k || this.heap.top() < val) {
this.heap.push(val)
if (this.heap.size() > this.k) {
this.heap.pop()
}
}
return this.heap.top()
};
总结
- 堆(优先队列)的思路: 看似数组 处理逻辑当成完全二叉树
- 最大最小的问题,保持堆的大小,定义好条件