1.Maximize Sum Of Array After K Negations
这道题我做麻烦了。我先找到了绝对值最小的数,在k允许的情况下优先翻转了负数,然后最后单独处理这个最小的数,决定它的正负号。runtime 和卡哥的应该差不多(?)
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
Arrays.sort(nums);
int res = 0, min = Math.abs(nums[0]), minIdx = 0;
for(int i = 0; i < nums.length; ++i){
if(Math.abs(nums[i]) < min){
min = Math.abs(nums[i]);
minIdx = i;
}
}
for(int i = 0; i < nums.length; ++i){
if(nums[i] < 0 && k > 0 && i != minIdx){
res += -nums[i];
--k;
}else if(i != minIdx){
res += nums[i];
}
}
res += k % 2 == 0? nums[minIdx] : -nums[minIdx];
return res;
}
}
这是第一次提交,超时,但通过大部分测试。应该是对的.
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int rem = 0, size = gas.length;
for(int start = 0; start < size; ++start){
int count = 0, dist = cost[start], cur = start;
rem = gas[start];
while(count < size){
if(rem >= dist){
rem -= dist;
++cur;
if(cur == size){
cur = 0;
}
rem += gas[cur];
dist = cost[cur];
}else{
break;
}
++count;
}
if(count == size) return start;
}
return -1;
}
}
这是卡哥的方法2. 分别考虑每个gas[i] - cost[i], 并把累计的和相加。一旦出现负数(比如第i位),说明从[0,i]区间任何地方开始,都不会是开始的点。因为如果是的话,车到那里就走不了了。可能存在0 < a < i使得[a,i]的和算下来>0嘛?不可能。因为,这样的话[0,a]的和就小于0. curSum在这之前就已经被清零了。
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int size = gas.length, sum = 0, start = 0, curSum = 0;
for(int i = 0; i < size; ++i){
int rest = gas[i] - cost[i];
curSum += rest;
if(curSum < 0){
start = i+1;
curSum = 0;
}
sum += rest;
}
if(sum < 0) return -1;
return start;
}
}
3.Candy
“得分高的一定要比neighbor高”可以拆分成两句话:从左向右看,如果右孩子比左孩子高,右孩子就比左孩子多1. 从右向左看,如果左孩子比右孩子高,左比右多1. 取两个数组最大值相加即可。
为什么取最大值,而不是两数组相加?假设有[a,b]如果ratings[a] < ratings[b],那么不可能ratings[b] < ratings[a]. 不可能同时满足两个规则。
很好的例子:[1,2,2,5,4,3,2]
class Solution {
public int candy(int[] ratings) {
int size = ratings.length, sum = 0;
if(ratings.length == 1) return 1;
int[] left = new int[size];
left[0] = 1;
int[] right = new int[size];
right[size-1] = 1;
for(int i = 1; i < size; ++i){
if(ratings[i] > ratings[i-1]){
left[i] = left[i-1] + 1;
}else{
left[i] = 1;
}
}
for(int i = size-2; i >= 0; --i){
if(ratings[i] > ratings[i+1]){
right[i] = right[i+1] + 1;
}else{
right[i] = 1;
}
}
for(int i = 0; i < size; ++i){
sum += Math.max(left[i], right[i]);
}
return sum;
}
}
文章提供了三个编程问题的解法:1)如何在允许进行K次翻转操作后最大化数组的和,策略是优先翻转较小的负数;2)解决GasStation问题,寻找能够完成环形行程的起点,通过遍历计算每个站点的剩余油量;3)Candy问题,分配糖果使得评分较高的孩子总是比邻居多至少一个糖果,通过左右遍历实现。

被折叠的 条评论
为什么被折叠?



