[路飞]_js算法:leetcode1046-最后一块石头的重量

114 阅读1分钟

leetcode 1046.最后一块石头的重量

问题描述: 有一堆石头,每块石头的重量都是正整数。

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

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

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

示例:

输入: [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],这就是最后剩下那块石头的重量。

思路: 用堆的思路实现 找到最重的 因此是维护一个大顶堆 (后附js实现堆)

/**
 * @param {number[]} stones
 * @return {number}
 */
var lastStoneWeight = function(stones) {
  const heap=new Heap((i,l)=>i>l);//大顶堆
    for(let i=0;i<stones.length;i++){
        heap.push(stones[i])
    }
    while(heap.size>1){
        let x=heap.pop();
        let y=heap.pop();
        if(x!=y){
            heap.push(Math.abs(x-y))
        }
    }
    if(heap.size){
        return heap.top
    }
    return 0;
};
//堆的实现
class Heap {
    constructor(cmp) {
        this.data = [];
        this.cmp = cmp;
    }
    get size() {
        return this.data.length;
    }
    get top() {
        return this.data[0];
    }
    getData() {
        return this.data;
    }
    swap(i, j) {
        [this.data[i], this.data[j]] = [this.data[j], this.data[i]];
    }
    // 向上冒泡
    up(i) {
        let index=this.data.length-1;
        while(index>0){
            let p=Math.floor((index-1)/2);
            if(p>=0&&this.cmp(this.data[index],this.data[p])){
                this.swap(index,p);
                index=p;
            }else{
                break;
            }
        }
    }
    // 下沉操作
    down(i) {
      if(this.data.length<2)return;
      let index=0,l=2*index+1,len=this.data.length;
      while(l<len){
        let r=l+1;
        if(r<len&&this.cmp(this.data[r], this.data[l]))l=r;
        if(this.cmp(this.data[index], this.data[l]))break;
        this.swap(index,l)
        index=l;
        l=index*2+1;
      }
    }
    push(item) {
      this.data.push(item);
      this.up();
    }
    //删除堆顶元素
    pop() {
        this.swap(0, this.data.length - 1);
        const res = this.data.pop();//已删除的元素(原来的堆顶元素)
        this.down();
        return res;
    }
  }