1005.K次取反后最大化的数组和
完成
思路:
题目虽然简单,但是要想清楚哪里用到了贪心的策略。
本题贪心的思路是,依次找最小的负值进行翻转,结束后如果k仍冗余,找最小的一个正数连续翻转,把k耗尽,让损失最小。
代码
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
int sum = 0;
Arrays.sort(nums);
// 把负值回正,直到k耗尽或没有负值
for (int i = 0; i < nums.length; i++) {
if(nums[i]<=0&&k>0){
nums[i] = -nums[i];
k--;
}else break;
}
// k比负值多,如果k是偶数,相当于没翻转
if(k%2!=0){
Arrays.sort(nums);
nums[0]=-nums[0];
}
for(int value : nums) sum+=value;
return sum;
}
}
134. 加油站
完成
代码
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int sum = 0;
int min = 0;
for (int i = 0; i < gas.length; i++) {
// 计算总油量-总消耗
sum += (gas[i] - cost[i]);
// 记录累加的油量和消耗的差的最小值
min = Math.min(sum, min);
}
if (sum < 0) return -1;
// 如果从0开始,min一直>0,则可以直接返回0
if (min >= 0) return 0;
for (int i = gas.length - 1; i > 0; i--) {
min += (gas[i] - cost[i]);
if (min >= 0) return i;
}
return -1;
}
}
135. 分发糖果
完成
思路:
本题需要综合考虑两边的rating,才能确定该元素的得分。但是同时考虑两边容易乱,因此先考虑左边,再考虑右边。
一开始的想法是先找到最小值,再从最小值开始依次向左遍历和向右遍历。但是这样对每个元素来说就只考虑了左边或右边,而不是左边和右边。
如果从头和尾遍历考虑左右情况,那么头尾元素应该分配多少糖果?这是我纠结的点,但其实只需要赋1即可,后面还会在左右遍历中更新。
代码
class Solution {
public int candy(int[] ratings) {
int[] res = new int[ratings.length];
res[0] = 1;
// 从前向后遍历,比较元素和其左边
for (int i = 1; i < res.length; i++) {
if(ratings[i]>ratings[i-1]){
res[i] = res[i-1]+1;
}else res[i] = 1;
}
// 从后向前遍历,比较元素和其右边
for (int i = ratings.length-2; i >= 0; i--) {
if(ratings[i]>ratings[i+1]){
// 这里不能直接赋值,要保留前向遍历的结果
res[i] = Math.max(res[i], res[i+1]+1);
}else res[i] = Math.max(1, res[i]);
}
return Arrays.stream(res).sum();
}
}