题目链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)
个人思路:很简单,先把数组里的元素按照绝对值大小排序,按照从大到小的顺序排序,排序之后遍历数组,将数组所有小于0的变成正数,如果小于0的数没变完,说明已经有了最大的和了,如果小于0的数变完了,但是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();
for(int i=0;i<nums.length;i++){
if(nums[i]<0&&k>0){
nums[i] = -nums[i];
k--;
}
}
if(k%2 == 1) nums[nums.length-1] = -nums[nums.length-1];
return Arrays.stream(nums).sum();
}
}
个人思路:第一步,判断总油量是否大于总消耗量,如果小于,则直接返回-1;如果大于,则进入第二步
第二步,定义一个剩余量的概念,剩余量指的是当前加油站的油量,减去去往下一个加油站所消耗的油量,也就是gas[i]-cost[i]。
第三步,定义一个累加值,累加值指的是剩余量的总和,如果在遍历累加的过程中,累加值小于0,那么我们的索引下标加一,累加值清零,直到遍历完之后,返回索引下标值,为什么累加值为零时,索引下标值要加一?
首先我们要知道,如果累加值为负数,说明我们到不了目的加油站。而我们目前在做的就是去寻找能够跑完一圈的起点在哪里,因此,当加上当前这个值的时候累加值为负数,说明当前这个值是小于0的,也就是说,假如我选择当前这个值为起点,那么我跑不到下一个加油站,所以我要选择当前这个值的下一个值。
代码
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);
curSum =0;
}
}
if(totalSum <0) return -1;
return index;
}
}
个人思路:这题比较难,使用两次贪心,第一次局部最优是从左到右遍历,只比较右孩子大于左孩子的情况。第二次局部最优是从右到左遍历,只比较左孩子大于右孩子的情况
candyVec[i] = Math.max(candyVec[i+1]+1,candyVec[i]);
candyVec[i] = (ratings[i]>ratings[i-1])?candyVec[i-1]+1:1;
这两行代码为什么要这么写,有一个例子[1,3,4,5,2],输出是11
代码
class Solution {
public int candy(int[] ratings) {
int len = ratings.length;
int[] candyVec = new int[len];
candyVec[0] = 1;
for(int i =1;i<len;i++){
candyVec[i] = (ratings[i]>ratings[i-1])?candyVec[i-1]+1:1;
}
for(int i = len-2;i>=0;i--){
if(ratings[i]>ratings[i+1]){
candyVec[i] = Math.max(candyVec[i+1]+1,candyVec[i]);
}
}
int ans=0;
for(int i:candyVec){
ans += i;
}
return ans;
}
}