[三分钟学算法]堆-模拟算法-最后一块石头的重量:有一堆石头,每块石头的重量都是正整数。每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。

文章目录

  • 题目详情
  • 算法原理
  • 编写代码

题目详情

有一堆石头,每块石头的重量都是正整数。

每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。

示例:

输入:[2,7,4,1,8,1]
输出:1
解释:
先选出 78,得到 1,所以数组转换为 [2,4,1,1,1],
再选出 24,得到 2,所以数组转换为 [2,1,1,1],
接着是 21,得到 1,所以数组转换为 [1,1,1],
最后选出 11,得到 0,最终数组转换为 [1],这就是最后剩下那块石头的重量。

提示:
1 <= stones.length <= 30
1 <= stones[i] <= 1000

算法原理

这个问题可以通过优先级队列(即最大堆)来模拟。

  1. 使用最大堆(PriorityQueue)来模拟每次选择两块最重石头的过程。
  2. 在每次操作中,先将石头的重量放入最大堆中(通过对石头的重量取负数,将其转化为最小堆的行为)。
  3. 每次从堆中取出两块最大石头,判断它们的关系:
  • 如果重量相等,两个石头都被粉碎。
  • 如果重量不等,剩余的石头的重量为 y - x,重新放回堆中。
  1. 如果堆中剩下一个石头,就返回这个石头的重量;如果堆中没有石头了,返回 0。

编写代码

class Solution {
    public int lastStoneWeight(int[] stones) {
        // 1. 创建一个大根堆
        PriorityQueue<Integer> heap = new PriorityQueue<>((a, b) -> b-a);
        // 2. 把所有的石头放进堆里
        for (int x : stones) {
            heap.offer(x);
        }
        // 3.模拟碰撞过程
        while (heap.size() > 1) {
            int a = heap.poll();
            int b = heap.poll();
            if (a > b) {
                heap.offer(a - b);
            }
        }
        return heap.isEmpty() ? 0 : heap.peek();
    }
}

你可能感兴趣的:(算法,java,数据结构,leetcode)