求:
每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 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
解:
1、堆排序
构造大顶堆,每次从堆出弹出2个元素,然后放入2者的差值(0也可以放进去,不会影响判断),当堆中只有1个元素时返回。
时间复杂度:O(NlogN)
空间复杂度:O(N)
public intlastStoneWeight(int[] stones) {
Queue q = newPriorityQueue<>((integer,t1) -> t1 - integer);for(inti = 0;i < stones.length;i++) {
q.offer(stones[i]);}
while(q.size() > 1) {
Integer t1 = q.remove();Integer t2 = q.remove();q.offer(Math.abs(t1 - t2));}
returnq.remove();}
2、直接对原始数组排序
每次都在for循环内部,将最大的2个元素放到数组末尾,然后进行运算,差值放数组末尾,数组倒数第二个元素变成0,在下一次的排序过程中,又会选出新一轮的最大和第二大的数放到数组末尾进行比较,整个过程一共需要持续stones.length-1次,最终返回数组最后一位的元素,它就是最大的。
这种方法是一种原地排序的方法,会改变原始数组。
时间复杂度:O(N^2logN)
空间复杂度:O(1)
public intlastStoneWeight(int[] stones) {
intindex = stones.length- 1;for(inti = 0;i < stones.length- 1;i++){
Arrays.sort(stones);stones[index] -= stones[index-1];stones[index-1] = 0;}
returnstones[stones.length-1];}