代码随想录算法训练营day 34 |1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果

1005.K次取反后最大化的数组和

代码随想录

思路:

先将数组排序(小→大),从第一个位置开始,比较本位置与下一个位置元素的大小,谁小翻转谁,遇到0停止。到最后一个位置时,如果还没翻转完K步,只翻转最后一个数。

代码:

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        Arrays.sort(nums);
        int res = 0;
        int index = 0;
        for(int i = 0; i < k; i++){//最多翻转k次,碰到0就停
            if(nums[index] == 0){
                break;
            //当比后一个数小时,翻转此数
            }else if(index < nums.length -1 && nums[index] <= nums[index + 1]){
                nums[index] = -nums[index];
            //只有index位置由-变+才会出现这种情况,说明该翻转下一个数了
            }else if(index < nums.length -1 && nums[index] > nums[index + 1]){
                ++index;
                nums[index] = -nums[index];
            //特殊情况,当index到数组的最后一个位置,不论正负,这个位置的数翻转对和的影响最小
            }else if(index == nums.length - 1){
                nums[index] = -nums[index];
            }
        }
        for(int num : nums){
            res+=num;
        }
        return res;
    }
}

需要注意的点:

1、当index到最后一个位置,没有下一个数可以比较,只对该位置翻转。因为index移动到最后一个位置,说明index-1已经翻转过了,变成正数,无论index的正负,其绝对值都比index-1小,翻转后能最大化数组和。

134. 加油站

代码随想录

思路:

计算走每个加油站增加/减少的油,累加>=0说明能跑完一圈。从i位置累加cursum,记作从i出发剩余的油,一但<0说明从i到目前循环的位置的加油站都不行,重置cursum,从后一个位置重新开始算。

代码:

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int cursum = 0;//检查从某点出发是否
        int total = 0;//检查是否能跑完一周
        int index = 0;
        for(int i = 0; i < gas.length; i++){
            cursum += gas[i] - cost[i];
            total += gas[i] - cost[i];
            if(cursum < 0){//说明从i出发图中油会不够
                //精简写法,记录新的起点,如果i到数组末尾,
                index = i + 1;
                cursum = 0;//重置
            }
        }
        if(total < 0) return -1;
        return index;
    }
}

需要注意的点:

1、代码的简洁性,循环一次就能解决问题。

135. 分发糖果

代码随想录

思路:

1、右边元素>左边元素,右边 = 左边+1,从前往后遍历。

2、左边元素>右边元素,左边 = 右边+1、已有左边中的最大值。

代码:

class Solution {
    public int candy(int[] ratings) {
        int[] candynum = new int[ratings.length];
        candynum[0] = 1;
        //右边比左边元素大就+1(左边元素奖励的基础上)
        for(int i = 1; i < ratings.length; i++){
            if(ratings[i] > ratings[i - 1]){
                candynum[i] = candynum[i - 1] + 1;
            }else{
                candynum[i] = 1;//就算右边不比左边大,也要填上1(初始化,每个人都有奖励)
            }
        }
        for(int i = ratings.length - 2; i >= 0; i--){
            if(ratings[i] > ratings[i + 1]){
                candynum[i] = Math.max(candynum[i + 1] + 1, candynum[i]);
            }
        }

        int res = 0;
        for(int num : candynum){
            res += num;
        }
        return res;
    }
}

需要注意的点:

1、比较并更新两个元素的奖励关系时,要用到已经更新的数据,所以,比较右>左要从前往后更新,比较左>右要从后往前更新。

2、第二次更新时,要取+1和已有的最大值,能保证同时满足与左右比较的条件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值