贪心算法
1005.K次取反后的最大化数组和
解题思路:
- 每次把最小值取反即能够构成最大数组和
- 因为若最小值是负数, 则其相反数就为正数, 最大利益化
- 若最小值是正数, 则其相反数是最小负数, 损失最小化
代码:
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
// 每次把最小的前面加个负号即可
// 动态的求数组的最大值或最小值---小顶堆
PriorityQueue<Integer> queue = new PriorityQueue<>();
for(int i:nums){
queue.offer(i);
}
for(int i=0; i<k; i++){
int min = queue.poll();
queue.offer(-min);
}
int sum = 0;
for(int num:queue){
sum += num;
}
return sum;
}
}
134.加油站
解题思路:
- 不断计算当前位置的剩余油量, 当遇到花费最多处, 那么最小剩余油量的下一个位置即是最佳开始的地方
代码:
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = cost.length;
int spare = 0;
int minIndex = 0;
int minSpare = Integer.MAX_VALUE;
for(int i=0; i<n; i++){
spare += gas[i] - cost[i];
if(spare <= minSpare){
minSpare = spare;
minIndex = i;
}
}
return spare < 0 ? -1 : (minIndex+1)%n;
}
}
135.分发糖果
解题思路:
- 先从左到右, 再从右到左, 鱼和熊掌不能兼得
代码:
class Solution {
public int candy(int[] ratings) {
int len = ratings.length;
int[] candy = new int[len];
candy[0] = 1;
// 1.从前向后处理
for (int i = 1; i < len; i++) {
candy[i] = (ratings[i] > ratings[i - 1]) ? candy[i - 1] + 1 : 1;
}
// 2.从后向前处理
for (int i = len - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1]) {
candy[i] = Math.max(candy[i], candy[i + 1] + 1);
}
}
return Arrays.stream(candy).sum();
}
}