代码随想录算法训练营第三十四天 | 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果
一、力扣1005.K次取反后最大化的数组和
题目链接
思路:按照绝对值从大到小排序,让绝对值大的负数转成正数,来消耗k,如果k没消耗完,且k为奇数,就再加上末尾的值即可。
class Solution {
public int largestSumAfterKNegations(int[] nums, int K) {
nums = IntStream.of(nums)
.boxed()
.sorted((o1, o2) -> Math.abs(o2) - Math.abs(o1))
.mapToInt(Integer::intValue).toArray();
int len = nums.length;
for (int i = 0; i < len; i++) {
if (nums[i] < 0 && K > 0) {
nums[i] = -nums[i];
K--;
}
}
if (K % 2 == 1) nums[len - 1] = -nums[len - 1];
return Arrays.stream(nums).sum();
}
}
二、力扣134. 加油站
题目链接
思路:如果能跑完一圈,那么gas和cost的加和一定大于等于0,也就说要找能跑完一圈的,直接for遍历求和即可,但是要找起点,那就从前往后加和,只要当前和小于0,那个起点一定不在已遍历的区间内,最起码也是i+1,记录下来,然后让当前和为0,再往后找,后面如果没有再小于0的和值出现,那记录的那个就是了,如果还有小于0 的,那就再记录下i+1。
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int curSum = 0, totalSum = 0, start = 0;
for (int i = 0; i < gas.length; i++) {
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
if (curSum < 0) {
start = i + 1;
curSum = 0;
}
}
if (totalSum < 0) return -1;
return start;
}
}
三、力扣135. 分发糖果
题目链接
思路:当前值如果比左右值都大,他分的糖果就得是最多的。因为既要考虑左边又要考虑右边,i=0没左边,两两比较i=1开始,i=1开始比较当前值是否比左值大,左边只考虑一个值,若从尾部开始考虑,是否比左值大,要从右边一直考虑到左边,所以考虑考虑左值是否比右值大只需要从i=1开始。
要考虑当前值是否比右值大,就不能从i=0开始这样要一直考虑到右边,所以考虑当前值是否比右值大,需要从len-2开始,比较的时候也要注意如果i的糖果大于i+1了就不用让i的糖果等于右边糖果数加一,比如1,2,3,0,1
class Solution {
public int candy(int[] ratings) {
int count = 0;
int[] total = new int[ratings.length];
total[0] = 1;
for (int i = 1; i < ratings.length; i++) {
total[i] = ratings[i] > ratings[i-1] ? total[i-1] + 1 : 1;
}
for (int i = ratings.length - 2; i >= 0; i--) {
if (ratings[i] > ratings[i+1]) {
total[i] = Math.max(total[i], total[i+1] + 1);
}
}
for (int i = 0; i < total.length; i++) {
count += total[i];
}
return count;
}
}