[路飞]_leetcode-1046-最后一块石头的重量

简介: leetcode-1046-最后一块石头的重量

网络异常,图片无法展示
|


[题目地址][B站地址]


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


每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 xy,且 x <= y。那么粉碎的可能结果如下:


  • 如果 x == y,那么两块石头都会被完全粉碎;
  • 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x


最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0


示例:


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


提示:


  • 1 <= stones.length <= 30
  • 1 <= stones[i] <= 1000


本题很简单,只需要根据题意要求,每次找出最大的两个值


如果相等,继续取出最大的两个值


如果不等,将它们的差值插入数组,继续取值 直到数组中元素的数量小于两个,此时返回数组中唯一的元素值或者 0 即可


基于以上解题思路,我们有三种方式解题


sort 排序


每次将数组进行升序排序,这样最大的两个值就是数组末尾的两个值


不断取出最大的两个值操作,直到数组中元素数量小于 2


代码如下:


var lastStoneWeight = function(stones) {
  // 当数组长度大于1的时候取出最大的两个值操作
  while(stones.length>1){
    // 将数组进行升序排序
    stones.sort((a,b) => a-b)
    // 排序后数组末尾的两个值就是最大的两个值
    const num1 = stones.pop(),
    num2 = stones.pop();
    // 如果两数不等,将差值插入数组
    if(num1!==num2) stones.push(num1-num2);
  }
  return stones[0]||0;
};
复制代码


二分算法


我们还可以只对数组进行一次排序,接下来每次有差值的时候


通过二分算法,在数组中找到第一个大于等于差值的位置进行插入


这样就不用每次都对数组进行排序了


代码如下:


var lastStoneWeight = function(stones) {
  // 首先对数组进行一次排序
  stones.sort((a,b) => a-b);
  // 当数组长度大于1的时候取出最大的两个值操作
  while(stones.length>1){
    const num1 = stones.pop(),
    num2 = stones.pop();
    // 如果两数不等,将差值通过二分算法查找合适的位置插入
    if(num1!==num2) stones = insert(stones,num1-num2);
  }
  // 二分算法插入差值
  function insert(arr,num){
    if(num<arr[0]) return [num,...arr]
    else if(num>arr[arr.length-1]) return [...arr,num]
    // 二分查找第一个大于等于num的位置
    let l = 0,r = arr.length-1;
    while(l<r){
      const mid = (l+r)>>1;
      if(arr[mid]<num) l = mid+1
      else r = mid;
    }
    // 将num插入
    arr.splice(l,0,num);
    return arr;
  }
  return stones[0]||0;
};
复制代码


大顶堆


涉及到维护最值的问题,都可以通过 来解题


本题需要获取的是数组的最大值,所以我们可以通过大顶堆来维护数组中的值,而堆顶元素就是数组中的最大值


每次取出堆顶的两个最大值进行操作 直到堆中的元素数量小于 2


代码如下:


// 大顶堆
class BigHeap{
  constructor(){
    this.arr = [];
    this.size = 0;
  }
  // 插入操作
  push(val){
    this.arr.push(val);
    this.size++;
    // 插入向上调整
    if(this.size>1){
      let cur = this.size-1,
      parent = (cur-1)>>1;
      while(cur>0&&this.arr[cur]>this.arr[parent]){
        [this.arr[parent],this.arr[cur]] =
        [this.arr[cur],this.arr[parent]]
        cur = parent,parent = (cur-1)>>1;
      }
    }
  }
  // 弹出操作
  pop(){
    if(this.size===0) return false;
    if(this.size===1){
      this.size = 0;
      return this.arr.pop();
    }
    const res = this.arr[0];
    this.arr[0] = this.arr.pop();
    this.size--;
    // 弹出向下调整
    let cur = 0,
    childl = 1,childr = 2;
    while(
      (childl<this.size&&this.arr[childl]>this.arr[cur]) ||
      (childr<this.size&&this.arr[childr]>this.arr[cur])
    ){
      if(childr<this.size&&this.arr[childr]>this.arr[childl]){
        [this.arr[cur],this.arr[childr]] =
        [this.arr[childr],this.arr[cur]]
        cur = childr;
      }else{
        [this.arr[cur],this.arr[childl]] =
        [this.arr[childl],this.arr[cur]]
        cur = childl;
      }
      childl = cur*2+1,childr = cur*2+2;
    }
    return res;
  }
}
var lastStoneWeight = function(stones) {
  // 创建大顶堆实例
  const heap = new BigHeap();
  // 将数组中元素插入堆中
  for(let i = 0;i<stones.length;i++){
    heap.push(stones[i])
  }
  // 当堆中元素数量大于1的时候取出最大的两个值操作
  while(heap.size>1){
    const num1 = heap.pop(),
    num2 = heap.pop();
    // 如果有差值,将差值插入堆中
    if(num1!==num2) heap.push(num1-num2);
  }
  return heap.pop()||0;
};
复制代码


至此我们就完成了 leetcode-1046-最后一块石头的重量


如有任何问题或建议,欢迎留言讨论!

相关文章
【Leetcode -766.托普利茨矩阵 -771.宝石与石头】
【Leetcode -766.托普利茨矩阵 -771.宝石与石头】
51 0
|
3月前
|
Python
【Leetcode刷题Python】1049. 最后一块石头的重量 II
LeetCode 1049题 "最后一块石头的重量 II" 的Python解决方案,通过动态规划算法计算使最后一块石头的重量最小的方案。
34 1
|
5月前
dp表,哈希表,力扣5.最长回文子串力扣1745.分割回文串IV力扣132.分割回文串II优先级队列(堆)是什么下面是手动实现小根堆力扣1046.最后一块石头的重量
dp表,哈希表,力扣5.最长回文子串力扣1745.分割回文串IV力扣132.分割回文串II优先级队列(堆)是什么下面是手动实现小根堆力扣1046.最后一块石头的重量
|
6月前
代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零
代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零
55 0
|
6月前
|
Java
leetcode-1049. 最后一块石头的重量 II
leetcode-1049. 最后一块石头的重量 II
51 0
|
12月前
|
算法 测试技术 容器
代码随想录算法训练营第四十二天 | LeetCode 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零
代码随想录算法训练营第四十二天 | LeetCode 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零
44 1
leetcode 1049 最后一块石头的重量
leetcode 1049 最后一块石头的重量
92 0
leetcode 1049 最后一块石头的重量
|
算法 Java
最后一块石头的重量 II(LeetCode 1049)
最后一块石头的重量 II(LeetCode 1049)
81 0
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
108 2