目录
1005.K次取反后最大化的数组和
本题简单一些,估计大家不用想着贪心 ,用自己直觉也会有思路。
题解思路:
解法就是先把数组按绝对值从大到小排列,然后先将数组里面的负数取反为整数,如果k的次数还剩余,在一个劲的逮着绝对值最小的数取反,这里对排在最后也是最小的数取反也有技巧就是如果剩余的k的次数是奇数,只需要最后的数取一次反即可,如果是偶数,取反过来取反过去,等于没取反,因此不用处理就行,最后就是按题意将数组中的各个数累加即可。
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
int result = 0;
Stream<Integer> integerNums = Arrays.stream(nums).boxed();// 将数组先转换成一个 Integer类型的stream流
Integer[] newNums = integerNums.toArray(Integer[]::new); //将流转换为数组
Arrays.sort(newNums, (o1,o2)->Math.abs(o2) - Math.abs(o1)); //将新数组按大到小排序,使用比较器排序时,必须是对引用类型的数组进行操作,即必须先将int类型的数组转换成Integer类型的数组。
for(int i = 0; i < newNums.length; i++){ //利用k次机会,先把数组中的绝对值较大的负数尽可能的都取反
if(newNums[i] < 0 && k > 0){
newNums[i] *= -1;
k--;
}
}
if(k % 2 != 0) newNums[newNums.length - 1] *= -1; //如果都把负数取反后还剩余k次,k若为奇数,把绝对值最小的数取反即可,k若为偶数,则不需要处理
for(Integer element : newNums){ //k次取反后累加数组中的各个元素就是最大化的数组和
result += element;
}
return result;
}
}
134. 加油站
本题有点难度,不太好想,推荐大家熟悉一下方法二
题解思路:
卡哥给的题解中没有模拟环绕一周的过程,只是遍历了一轮数组后,可以这么思考:
1、总净增油量是一定的,因此遍历一轮就可以判断是否可以环绕一周,如果总净增油量大于等于0,说明可以,反之不可以;
2、出发站点只能从这n个加油站,也就是gas下标索引值范围内选择,这里注意如果totalSum小于0的话,此时有可能出现start = n + 1,也就是数组越界,但是总净增油量小于0,下面代码会执行返回-1,不会返回start的值;如果totalSum大于等于0的话,一定不会出现start = n + 1的情况,最顶的话也就是start = n,也就是从最后一个站点出发,因为前面正增油量太小了,加上第n个站点的正增油量才能抵消消耗的油量,使得最后totalSum大于等于0。
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int totalSUm = 0;
int currentSum = 0;
int start = 0;
for(int i = 0; i < gas.length; i++){
currentSum += gas[i] - cost[i]; //计算每个加油站点的总净增油量,如果是负数则表示不能从出发点加油站到开往到正在遍历的第i个加油站,如果是正数表示到达后剩余的油量,即可以到达
totalSUm += gas[i] - cost[i]; //计算一轮即所有站点的净增油量如果是负数,表示不管从哪个点出发都不可能环绕一周
if(currentSum < 0) { //前面的每个和累加净增油量与当前的负增油量相加小于0,说明不能走到当前遍历的第i个站点,因此需要换从下一个站点开始
start = i + 1; //如果前面的所有正数累加都抵不过当前第i个站点的负增油量,那么从前面的每个正的净增油量站点出发都不可能到达第i个站点,就需要从下一个站点去重新判断了。这里注意如果totalSum小于0的话,此时有可能出现start = n + 1,也就是数组越界,但是总净增油量小于0,下面代码会执行返回-1,不会返回start的值;如果totalSum大于等于0的话,一定不会出现start = n + 1的情况,最顶的话也就是start = n,也就是从最后一个站点出发,因为前面正增油量太小了,加上第n个站点的正增油量才能抵消消耗的油量,使得最后totalSum大于等于0,
currentSum = 0; //重新判断时需要将正净增油量累加的初始值置为0
}
}
if(totalSUm < 0 ) return -1; //如果总的净增油量小于0,那么一定不会环绕一周
return start;
}
}
135. 分发糖果
本题涉及到一个思想,就是想处理好一边再处理另一边,不要两边想着一起兼顾,后面还会有题目用到这个思路
题解思路:
我们取序列中的任意三点B1 A B2,如果 A > B2 ,则按照左规则处理后,B2不会比A多;按照右规则处理后,A一定比B2多,那么A一定会被更新(变大),此时变大后的A才会满足比右边分高时,分的糖果数量要更多
class Solution {
public int candy(int[] ratings) {
int[] candyCount = new int[ratings.length];
Arrays.fill(candyCount, 1);
for(int i = 1; i < ratings.length; i++){
if(ratings[i] > ratings[i - 1]){ //左规则:只判断右边比左边大的情况下,给每个小孩发放的数量,此时从前往后遍历
candyCount[i] = candyCount[i - 1] + 1;
}
}
for(int i = ratings.length - 2; i >= 0; i--){ //右规则:只判断左边比右边大的情况下,给每个小孩发放的数量,此时从后往前遍历,此时更新糖果数组中数量最大的值,才能满足某个孩子比左右两个孩子分都高时,分得的糖果数量会更多
if(ratings[i] > ratings[i + 1]){
candyCount[i] = Math.max(candyCount[i], candyCount[i + 1] + 1); //更新右规则下的A
}
}
int result = 0;
for(int element : candyCount){
result += element;
}
return result;
}
}