[路飞]_leetcode_1046. 最后一块石头的重量

91 阅读1分钟

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

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

如果 x == y,那么两块石头都会被完全粉碎; 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。 最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。

解题思路

这一题简单的做法是将数组按降序排序,然后每次取2个数,做减法,如果结果不为0则将当前值重新插入到数组中,直到数组长度 < 2。

除了上述的方法,也可以通过大顶堆来实现,每次取2个最大数石头做减法,如果石头不为0则重新插入到堆中。

代码

class Heap {
    constructor() {
        this.data = [];
    }

    swap(i, j) {
        [this.data[i], this.data[j]] = [this.data[j], this.data[i]]
    }

    compartor(i, j) {
        return this.data[i] - this.data[j];
    }

    size() {
        return this.data.length;
    }

    peek() {
        if (!this.size()) return null;
        return this.data[0]
    }

    offer(val) {
        this.data.push(val);
        this.bubbleUp(this.data.length-1);
    }

    pop() {
        if (!this.size()) return null;
        let res = this.data[0];
        if (this.size() > 1) {
            this.data[0] = this.data.pop();
            this.bubbleDown(0);
        } else {
            this.data.pop();
        }
        return res;
    }

    bubbleUp(index) {
        while(index) {
            let parent = (index - 1) >> 1;
            if (this.compartor(index, parent) > 0) {
                this.swap(index, parent);
                index = parent;
            } else {
                break;
            }
        }
    }

    bubbleDown(index) {
        let last = this.data.length - 1;
        while(index < last) {
            let temp = index, left = index * 2 + 1, right = index * 2 + 2;
            if (left <= last && this.compartor(left, temp) > 0) {
                temp = left;
            }
            if (right <= last && this.compartor(right, temp) > 0) {
                temp = right;
            }
            if (temp == index) break;
            this.swap(temp, index);
            index = temp;
        }
    }
}
var lastStoneWeight = function(stones) {
    if (stones.length < 2) return stones[0] ? stones[0] : 0;
    let h = new Heap();
    for (i of stones) {
        h.offer(i);
    }

    while(h.size() > 1) {
        let x = h.pop();
        let y = h.pop();
        if (x !== y) h.offer(x-y);
    }

    if (!h.size()) return 0;
    return h.peek()
};