一.题目
1046. 最后一块石头的重量 - 力扣(LeetCode)

二.思路讲解
2.1 思路讲解
本题要求不断取出最重的两块石头 进行粉碎,直到剩下最多一块石头。由于需要快速获取最大值 ,我们可以使用最大堆(大根堆)来存储所有石头的重量。
三.代码演示
cpp
class Solution {
public:
int lastStoneWeight(vector<int>& stones)
{
priority_queue<int> heap;//创建大堆
//把元素加入堆中
for(const auto& x : stones)
{
heap.push(x);
}
//一次要取两个元素
while(heap.size() > 1)
{
int a = heap.top();
heap.pop();
int b = heap.top();
heap.pop();
//若不相同
if(a != b)
heap.push(a - b);
//相同
else
heap.push(0);
}
return heap.top();
}
};
四.代码讲解
一、数据结构选择
由于题目要求每次取出最重的两块石头 ,我们需要一种能够快速获取最大值 的数据结构。C++ 的 priority_queue 默认是大根堆,非常适合本题。
二、主函数 lastStoneWeight
-
创建最大堆 :
priority_queue<int> heap;。 -
将所有石头重量压入堆 :遍历
stones数组,对每个元素执行heap.push(x)。 -
循环模拟粉碎过程:当堆中元素个数大于 1 时,重复以下步骤:
-
取出堆顶(最大值)作为
a,并弹出。 -
取出新的堆顶(次大值)作为
b,并弹出。 -
若
a != b,则将差值a - b压回堆中(注意:题目定义中y ≥ x,这里a是较大值,b是较小值,所以a - b非负)。 -
若
a == b,则两块石头完全粉碎,不产生新石头(代码中压入 0,但实际可以不压入;压入 0 不影响后续结果,但会多一次操作)。
-
-
返回结果 :循环结束后,堆中可能剩余 1 个石头,也可能为空(若所有石头均粉碎)。代码中直接
return heap.top(),当堆为空时会出错,但题目保证最后最多剩一块,且初始至少有一个石头,所以堆非空。若所有石头都粉碎,堆中会有一个 0(因为相等时压入 0),因此返回 0 正确。
三、关键细节
-
大根堆的特性 :
priority_queue<int>默认是最大堆,堆顶元素是最大值,适合本题需求。 -
取出顺序 :先取
a(最大值),再取b(次大值),保证a ≥ b。 -
差值计算 :直接用
a - b得到新石头的重量(非负)。
五、流程图
