1005.K次取反后最大化的数组和
两次贪心算法思路
1. 数组中有负数时,把绝对值最大的负数取反
2. 数组全为非负数时,一直取反最小的那个数
步骤:
- 第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
- 第二步:从前向后遍历,遇到负数将其变为正数,同时K--
- 第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
- 第四步:求和
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
Arrays.sort(nums);
for(int i=0;i<nums.length&&nums[i]<0&&k>0;i++,k--){
nums[i]=-nums[i];
}
int res = 0, min = Integer.MAX_VALUE;
for(int num:nums){
res+=num;
min = Math.min(min,num);
}
return res - (k%2)*min*2;
}
}
134. 加油站
start=i+1 发生在数组最后,是否会产生数组溢出的问题:
当发生这种情况说明,肯定是直接返回-1了,不需要考虑溢出问题:来源视频评论区
反正法:来源:代码随想录
那有没有可能 [0,i] 区间 选某一个作为起点,累加到 i这里 curSum是不会小于零呢? 如图:
如果 curSum<0 说明 区间和1 + 区间和2 < 0, 那么 假设从上图中的位置开始计数curSum不会小于0的话,就是 区间和2>0。
区间和1 + 区间和2 < 0 同时 区间和2>0,只能说明区间和1 < 0, 那么就会从假设的箭头初就开始从新选择其实位置了。与同一逻辑下等到区间和2之后才转变起始位置相矛盾
// 解法2
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int curSum = 0;
int totalSum = 0;
int index = 0;
for (int i = 0; i < gas.length; i++) {
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
if (curSum < 0) {
index = (i + 1) % gas.length ;
curSum = 0;
}
}
if (totalSum < 0) return -1;
return index;
}
}
135. 分发糖果
先全部判断左边的关系
第二次全部判断右边的关系(此时需要从后往前遍历,因为 rating[5]与rating[4]的比较 要利用上 rating[5]与rating[6]的比较结果)