目录
1.题目->
/*有一堆石头,每块石头的重量都是正整数。
每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 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.数组中的元素全部消去不剩下任何元素2.数组中还剩下两个不相同的元素,最后消去小的大的变成差值,只剩下一个元素)。
该题需要注意的细节->
1.首先题目要求我们从两个最大的值开始消去,为使时间复杂度更低,我们得先对数组进行排序
2.数组不能够直接的删除元素,因此给定的数组stones不能作为增删查改的对象
3.如果选取的两个元素大小不一样,小的那个要从容器中删去,大的那个要变成两者的差值
4.最后要求返回的是石头的重量,而不是返回最后的数组,因此要使用索引取出该重量并return
2.更容易理解的代码(建议新手)
代码->
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
class Solution {
public int lastStoneWeight(int[] stones) {
//把数组变成集合容易计算
List list = new ArrayList();
for (Integer x : stones) {
list.add(x);
}
while (true) {
if (list.size() == 1 || list.size() == 0) {
break;
}
//对集合进行排序
list.sort(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return (int) o1 - (int) o2;
}
});
//对两个最大值进行操作
if (list.get(list.size() - 2) == list.get(list.size() - 1)) {
list.remove(list.get(list.size() - 2));
list.remove(list.get(list.size() - 1));
} else {
list.set(list.size() - 1, (int) list.get(list.size() - 1) - (int) list.get(list.size() - 2));
list.remove(list.get(list.size() - 2));
}
}
if (list.size() == 0) {
return 0;
}
return (int) list.get(0);
}
}
public class Test {
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.lastStoneWeight(new int[]{2, 7, 4, 1, 8, 1}));
System.out.println(solution.lastStoneWeight(new int[]{2, 2}));
}
}
核心思想->
1.先把数组放入一个List集合中方便后面对数据的增删查改 - 使用List类中的add方法
List list = new ArrayList();
for (Integer x : stones) {
list.add(x);
}
2.再把集合按照升序(降序也可以)的排列方式,对其进行排序 - 使用List类中的sort方法
在这里我使用lambda式的形式(匿名内部类的简写)
list.sort(( o1, o2) -> (int) o1 - (int) o2
3.排好序后,最后两个数据一定是当前集合最大的两个元素,对其进行判断是否相等,相等则都消去
- 使用List类中的remove方法
不同则下去前一个数据,并把最后一个数据赋值成两数差值 - 使用List类中的set方法
if (list.get(list.size() - 2) == list.get(list.size() - 1)) {
list.remove(list.get(list.size() - 2));
list.remove(list.get(list.size() - 1));
} else {
list.set(list.size() - 1, (int) list.get(list.size() - 1) - (int) list.get(list.size() - 2));
list.remove(list.get(list.size() - 2));
}
4.最后,因为上述是一个循环的过程,所以要将其放入循环当中,循环终止的条件就是集合中没有数据或者只剩下一个数据。
3.更简洁的代码(使用Queue队列)
代码->
import java.util.PriorityQueue;
class Slove {
public int lastStoneWeight(int[] stones) {
//创建队列并通过调用构造方法将数据进行排序
PriorityQueue<Integer> pq = new PriorityQueue<Integer>((a, b) -> b - a);
//通过增强for把数据加入到队列中
for (int stone : stones) {
pq.offer(stone);//offer插入元素方法
}
while (pq.size() > 1) {
int a = pq.poll();//poll检索开头的数据,并把数据删除
int b = pq.poll();
if (a > b) {
pq.offer(a - b);
}
}
return pq.isEmpty() ? 0 : pq.poll();
}
}
public class Answer {
public static void main(String[] args) {
Slove slove = new Slove();
System.out.println(slove.lastStoneWeight(new int[]{2, 7, 4, 1, 8, 1}));
System.out.println(slove.lastStoneWeight(new int[]{2, 2}));
}
}
核心思想->
1.创建一个PriorityQueue的队列,并使用带参的构造方法意在把传入的数据进行降序(升序也可以)处理,然后把数组中的数据使用增强for放入队列中 - PriorityQueue类中的offer方法
PriorityQueue<Integer> pq = new PriorityQueue<Integer>((a, b) -> b - a);
//通过增强for把数据加入到队列中
for (int stone : stones) {
pq.offer(stone);//offer插入元素方法
}
2.然后通过循环删去降序后的开头的两个元素,并判断两个元素若不相等则插入它们两个数的差值,若相等则不做其他处理 - PriorityQueue中的poll方法和offer方法
while (pq.size() > 1) {
int a = pq.poll();//poll检索开头的数据,并把数据删除
int b = pq.poll();
if (a > b) {
pq.offer(a - b);
}
}
3.最后使用三元运算符对最后的队列进行判断是否为空,若为空则直接返回0,若不为空则返回队列中的那个唯一的元素。
return pq.isEmpty() ? 0 : pq.poll();
4.总结->
队列在算法中的使用是很频繁的,同样也是很方便的,不仅能使代码看起来简洁,而且还降低了时间复杂度。所以,不管哪种方法,队列的这种方法都必须熟练的学会并使用!