1. K 次取反后最大化的数组和
1005. K 次取反后最大化的数组和 - 力扣(LeetCode)
按绝对值从大到小排序
再从前开始反转负数,这样反转过来的都是大的正数
如果反转次数还剩余奇数次,就反转最后一个数(绝对值最小的)
偶数次,不用反转
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();
int len = nums.length;
for (int i = 0; i < len; i++) {
//从前向后遍历,遇到负数将其变为正数,同时K--
if (nums[i] < 0 && k > 0) {
nums[i] = -nums[i];
k--;
}
}
// 如果K还大于0,那么反复转变数值最小的元素,将K用完
if (k % 2 == 1) nums[len - 1] = -nums[len - 1];
return Arrays.stream(nums).sum();
}
}
- 时间复杂度: O(nlogn)
- 空间复杂度: O(1)
2. 加油站
curSum < 0 意味着之前的所有点都不能作为起点
只能从下一个作为起点,再进行尝试
如果当前点已经是最后一个了,i+1超过数组长度(for循环结束,totalSum < 0,会返回 -1)
如果totalSum < 0 意味着不存在满足条件的起点
totalSum > 0 则一定存在满足条件的起点 (通过curSum寻找符合的起点)
也可以先求得totalSum,判断是否有起点
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int length = gas.length;
int curSum = 0;
int start = 0;
int totalSum = 0;
for(int i = 0; i < length; i++){
totalSum += gas[i] - cost[i];
curSum += gas[i] - cost[i];
if(curSum < 0){
curSum = 0;
start = i + 1;
}
}
if(totalSum < 0)
return -1;
return start;
}
}
3. 分发糖果
- 一次是从左到右遍历,只比较右边孩子评分比左边高的情况。
更高,则右边=左边+1,否则 =1
- 一次是从右到左遍历,只比较左边孩子评分比右边高的情况。
更高,则左边 = 右边+1和之前结果取最大值(因为还要保证比它的左边大,所以不能比之前的结果小)否则不变
class Solution {
public int candy(int[] ratings) {
int length = ratings.length;
int[] candy = new int[length];
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;
}
for(int i = length-2; i > -1; i--){
if(ratings[i] > ratings[i+1]){
candy[i] = Math.max(candy[i], candy[i+1] + 1) ;
}
}
int res = 0;
for (int num : candy) {
res += num;
}
return res;
}
}