【第33天】加油站和分发糖果需要复习思路!!加油!

文章提供了三个编程问题的解法:1)如何在允许进行K次翻转操作后最大化数组的和,策略是优先翻转较小的负数;2)解决GasStation问题,寻找能够完成环形行程的起点,通过遍历计算每个站点的剩余油量;3)Candy问题,分配糖果使得评分较高的孩子总是比邻居多至少一个糖果,通过左右遍历实现。

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;
    }
}

2.Gas Station

这是第一次提交,超时,但通过大部分测试。应该是对的.

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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值