力扣题目 1005.K次取反后最大化的数组和
思路
- 先把数组排序,从小到大排序
- 然后将负的反转。当k=0,负的还没有转完或者刚转完,就全部元素相加;当k还大于0时,负的已经反转完,那就判断k的奇偶性,反复反转自己就行
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
int sum = 0;
//排序数组
Arrays.sort(nums);
int length = nums.length;
//反转负数
for(int i=0; i<length; i++){
if(nums[i] < 0 && k > 0){
nums[i] = -nums[i];
k--;
}
sum += nums[i];
}
//当反转完所有负数,k仍然大于0
if(k > 0){
Arrays.sort(nums);
//此时反复反转本身
int time = k % 2;
//当time为1时,只需要减去最小的元素nums[0];time为0不需要减,也就是减去0
sum -= time*nums[0]*2;
}
return sum;
}
}
为什么需要减去两倍呢?
不懂的可以用不要*2,用例子(nums = 4,2,3; k = 1)手动模拟一遍,或者debug一下就会明白。
力扣题目 134.加油站
思路
- 暴力解法:
- 用两个循环,嵌套循环来实现。大循环用来以哪个为起点,小循环是用来跑一圈
- 这个解法问题在于怎么跑一圈呢?怎么循环遍历?
- 用for的话可以用数组的长度来解决;
- 当如果用while的时候,用 int index = (i + 1 )% cost.size 取余来遍历,当index = i 的时候就是跑完一圈。
- 贪心的解法
- 局部最优:当前累加rest【i】的和curSum一旦小于0,起始位置至少要是i+1,要是后面还有小于0,继续更新起始位置 i+1。
- 全局最优:找到可以跑一圈的起始位置
- 局部最优可以推出全局最优,找不出反例,试试贪心。
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int length = gas.length;
int curSum = 0; //记录从i位置开始的油量是否为负
int totalSum = 0; //总油量,当总油量为负的时候直接返回-1
int index = 0; //需要返回的位置,curSum为负时需要更新这个位置
for(int i=0; i<length; i++){
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
if(curSum < 0){
curSum = 0;
index = i+1;
}
}
if(totalSum < 0)
return -1;
return index;
}
}
力扣题目 135.分发糖果
思路
- 当遇到这样类似的比较题目,不要两边同时比较,应该先比较一边,再比较另一边。
- 、从哪边开始比较,应该从哪边开始遍历顺序
class Solution {
public int candy(int[] ratings) {
int length = ratings.length;
int[] candy = new int[length];
int sum = 0;
//先从左到右遍历
//又因为在循环里面i直接从1开始遍历,所以当i为0的时候就需要初始值
candy[0] = 1; //至少分配一个糖果
for(int i=1; i<length; i++){
if(ratings[i] > ratings[i-1])
candy[i] = candy[i-1] + 1;
else
candy[i] = 1;
}
sum += candy[length-1];
//从右到左遍历
for(int i = length-2; i>=0; i--){
if(ratings[i] > ratings[i+1])
candy[i] = Math.max(candy[i], candy[i+1]+1);
//当右边比左边大的时候,也是求最大值,但是可以留有原来的值
//总和
sum += candy[i];
}
return sum;
}
}