1. 优先级队列(堆)基础概念解析
优先级队列(Priority Queue)是一种特殊的队列数据结构,它不同于普通的先进先出(FIFO)队列,而是根据元素的优先级来决定出队顺序。在Java中,优先级队列通常通过堆(Heap)这种数据结构来实现。
堆是一种完全二叉树,满足以下性质:
- 大根堆:每个节点的值都大于或等于其子节点的值
- 小根堆:每个节点的值都小于或等于其子节点的值
Java中的PriorityQueue类默认实现的是小根堆,但可以通过自定义比较器来改变其行为。堆的主要操作及其时间复杂度如下:
- 插入元素(offer):O(log n)
- 删除堆顶元素(poll):O(log n)
- 获取堆顶元素(peek):O(1)
注意:虽然堆的插入和删除操作的时间复杂度都是O(log n),但构建一个包含n个元素的堆的时间复杂度是O(n),而不是O(n log n),这是因为构建堆的过程可以利用更高效的算法。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 经典堆应用问题解析
2.1 最后一块石头的重量(LeetCode 1046)
问题描述
有一堆石头,每块石头的重量都是正整数。每次选择最重的两块石头进行粉碎,如果重量相同则都消失,否则较轻的石头消失,较重的石头重量变为两者之差。重复这个过程直到只剩一块或没有石头,返回最后剩下的石头的重量。
算法实现
java复制class Solution {
public int lastStoneWeight(int[] stones) {
// 创建大根堆,通过自定义比较器实现
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
// 将所有石头放入堆中
for (int stone : stones) {
maxHeap.offer(stone);
}
// 模拟粉碎过程
while (maxHeap.size() > 1) {
int first = maxHeap.poll(); // 最重的石头
int second = maxHeap.poll(); // 第二重的石头
int diff = first - second;
if (diff > 0) {
maxHeap.offer(diff); // 将剩余部分放回堆中
}
// 如果diff == 0,两块石头都消失,无需处理
}
// 返回结果
return maxHeap.isEmpty() ?
