【路飞】1046. 最后一块石头的重量

109 阅读1分钟

1046. 最后一块石头的重量

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

每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 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],这就是最后剩下那块石头的重量。

解题思路:本体纯数组才做比较简单,这里就不介绍了,直接上大顶堆实现方式,大顶堆介绍可以参考最小的k个数,代码如下:

var lastStoneWeight = function(stones) {
    if(!stones) return 0;
    data = [];
    cnt = 0;
    for(let i = 0; i < stones.length; i ++){
        //让无序数组有大顶堆特性
        push_up(stones[i]);
    }
    //如果只有一个数,直接返回
    if(data.length == 1) return data[0];
    //开始跳石头粉碎
    while(data.length > 1){
        //大顶堆特性根节点最大,获得最大数
        let x = data[0];
        //删除最大根节点
        pop_down();
        //删除最大后,因为维护了根特性,此时最大值就是根节点
        let y = data[0];
        pop_down();
        //判断第一大值和第二大值是否相等,如果不相等就入队两者差
        if(x != y){
             push_up(x - y)
        }
    }
    return data[0] ? data[0] : 0;
};

let data = [],cnt = 0;
var push_up = function(val){
    data.push(val);
    let idx = cnt;//当前节点
    let gIdx = parseInt((idx - 1) / 2);//根节点
    while(idx && data[idx] > data[gIdx]){
        //交互节点,向上调整
        swap(data[idx],idx,data[gIdx],gIdx);
        idx = gIdx;
        gIdx = parseInt((idx - 1)/2);
    }
    cnt ++;
    return;
}

var pop_down = function(){
    if(data.length <= 1){
        data = [];
        cnt = 0;
        return;
    }
    //删除最大值,将尾结点放在开头,位置树结构
    data[0] = data.pop();
    cnt --;
    let idx = 0;//当前节点
    let n = cnt -1;//最大节点个数
    let zIdx = 2 * idx + 1;//左子节点
    //左节点小于n就说明存在左子节点
    while(zIdx <= n){
        let temp = idx;//三角区最大值下标
        if( data[idx] < data[zIdx] ) temp = zIdx;
        //判断右子节点是否存在,然后比较大小,选出最大值的下标
        if(zIdx + 1 <= n && data[temp] < data[zIdx + 1]) temp = zIdx + 1;
        if(temp == idx) break;//相等说明没必要调整,根节点已经是最大的
        //交互根节点和最大子节点,保持向下调整
        swap(data[idx],idx,data[temp],temp);
        idx = temp;
        zIdx = 2*idx +1;
    }
    return;
}

var swap = function(v1,i1,v2,i2){
    data[i1] = v2;
    data[i2] = v1;
}