1005. Maximize Sum Of Array After K Negations
这题的思路是先遍历数组,在k次数允许的前提下,把所有的负数先反转了。这样需要先把数组按照绝对值大小排序,排序从大到小。 在k次数用完的话, 算出总sum值返回即可。 未用完的话,就挑一个绝对值最小的,即排序后数组最后一位,反复反转直到k为0。
这题的思路误入的歧途有两个,第一个是没考虑绝对值排序,而是分开考虑负数,0和正数的处理。逻辑很繁琐。 第二个是没考虑直接改数组值。不改数组值的话,也有很多麻烦。
最后一点,java的Arrays.sort居然不支持lambda的比较函数。
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
nums = IntStream.of(nums)
.boxed()
.sorted((a,b)->Math.abs(b) - Math.abs(a))
.mapToInt(Integer::intValue).toArray();
for(int i=0; i<nums.length; i++) {
if(nums[i] < 0 && k>0) {
nums[i] = (-1) * nums[i];
k--;
}
}
if(k>0) {
while(k>0) {
nums[nums.length - 1] = (-1) * nums[nums.length - 1];
k--;
}
}
return Arrays.stream(nums).sum();
}
}
134. Gas Station 这题倒是找到思路了,但按照我的思路的写法,有很多边界条件,调了好几次才成功。 Carl的思路是,当前累加rest[i]的和curSum一旦小于0,起始位置至少要是i+1,因为从i之前开始一定不行。全局最优:找到可以跑一圈的起始位置。 这个思路写出来的就很简洁。计算一个油量为正的区间,一旦油量为负,startIdx就更新为下一个元素,油量清零。 同时保存一个总油量判断是否有解。
我的思路是,也是保存一个当前油量,在负的时候不做记录,在油量为正的时候,记录起始点。若油量转负,重新计算起始点。这个思路也能写出来,但边界条件很多。不要用,容易写错。
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int len = gas.length;
if(gas.length != cost.length || len <= 0) {
return -1;
}
int bal = 0;
int start_idx = 0;
int curBal = 0;
for(int i=0; i<len; i++) {
int curDiff = gas[i] - cost[i];
bal += curDiff;
curBal += curDiff;
if(curBal < 0) {
start_idx = i+1;
curBal = 0;
}
}
if(bal < 0) {
return -1;
}
return start_idx;
}
}
135. Candy 这题彻底没思路了。走进了所谓的同时考虑局部的两侧,结果思路似乎有,但一想就几乎是写不出来的。 正确思路为:
- 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
- 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
这样从局部最优推出了全局最优,即:相邻的孩子中,评分高的孩子获得更多的糖果。
思路选对了就很好写。
class Solution {
public int candy(int[] ratings) {
int len = ratings.length;
int[] candyArr = new int[len];
candyArr[0] = 1;
for(int i=1; i<len; i++) {
if(ratings[i] > ratings[i-1]) {
candyArr[i] = candyArr[i-1] + 1;
}
else {
candyArr[i] = 1;
}
}
for(int i=len-2; i>=0; i--) {
if(ratings[i] > ratings[i+1]) {
candyArr[i] = Math.max(candyArr[i], candyArr[i+1] + 1);
}
}
int ans = 0;
for(int num : candyArr) {
ans += num;
}
return ans;
}
}