一、题目
有一堆石头,每块石头的重量都是正整数。
每一回合,从中选出两块最重的石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/last-stone-weight
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路
这里,我们手动建立一个大堆的优先级队列,将stones里边的元素添加到这个定义的优先级队列中 ,判断 x 和 y 的值(始终x <= y),将优先级队列中最大的两个元素取出来,如果x!=y就向队列中 添加一个y-x的值。x == y 的话,就不用将取出来的元素添加进去,这里需要判断取出两个最大的元素后,队列是否为空,若为空,直接返回0。
三、代码
class MyPriorityQueue {
// 以大堆为例子
private int[] array = new int[30];
private int size = 0;
public void offer(int val) {
array[size] = val;
size++;
// 把新加入的元素进行向上调整
shiftUp(array, size - 1);
}
public int getSize() {
return size;
}
private static void shiftUp(int[] array, int index) {
int child = index;
int parent = (index - 1) / 2;
while (child > 0) {
if (array[parent] < array[child]) {
int tmp = array[parent];
array[parent] = array[child];
array[child] = tmp;
} else {
break;
}
child = parent;
parent = (child - 1) / 2;
}
}
// 将队首元素删掉并返回,同时保持堆结构
public int poll() {
int result = array[0];
array[0] = array[size - 1];
size--;
shiftDown(array, size, 0);
return result;
}
private static void shiftDown(int[] array, int size, int index) {
int parent = index;
int child = 2 * parent + 1;
while (child < size) {
if (child + 1 < size && array[child] < array[child + 1]) {
child = child + 1;
}
if (array[parent] < array[child]) {
int tmp = array[parent];
array[parent] = array[child];
array[child] = tmp;
} else {
break;
}
parent = child;
child = 2 * parent + 1;
}
}
public int peek(){
return array[0];
}
public boolean isEmpty(){
return size == 0;
}
}
class Solution{
public int lastStoneWeight(int[] stones) {
MyPriorityQueue queue = new MyPriorityQueue();
for (int i = 0; i <stones.length ; i++) {
queue.offer(stones[i]);
}
while(queue.getSize() > 1){
int x = queue.poll();
int y = queue.poll();
// 保证 y 是大的一个
if (x > y){
int tmp = x;
x = y;
y = tmp;
}
if (x != y){
queue.offer(y-x);
}
if (queue.isEmpty()){
return 0;
}
}
return queue.peek();
}
}