代码随想录 Day-22

力扣题目 1005.K次取反后最大化的数组和

思路

  • 先把数组排序,从小到大排序
  • 然后将负的反转。当k=0,负的还没有转完或者刚转完,就全部元素相加;当k还大于0时,负的已经反转完,那就判断k的奇偶性,反复反转自己就行

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        int sum = 0;

        //排序数组
        Arrays.sort(nums);
        int length = nums.length;

        //反转负数
        for(int i=0; i<length; i++){
            if(nums[i] < 0 && k > 0){
                nums[i] = -nums[i];
                k--;
            }
            
            sum += nums[i];
        }

        //当反转完所有负数,k仍然大于0
        if(k > 0){
            Arrays.sort(nums);
            
            //此时反复反转本身
            int time = k % 2;

            //当time为1时,只需要减去最小的元素nums[0];time为0不需要减,也就是减去0
            sum -= time*nums[0]*2;
        }

        return sum;
    }
}

为什么需要减去两倍呢?

不懂的可以用不要*2,用例子(nums = 4,2,3; k = 1)手动模拟一遍,或者debug一下就会明白。


力扣题目 134.加油站

思路

  1. 暴力解法:
    1. 用两个循环,嵌套循环来实现。大循环用来以哪个为起点,小循环是用来跑一圈       
    2. 这个解法问题在于怎么跑一圈呢?怎么循环遍历?
      1. 用for的话可以用数组的长度来解决;
      2. 当如果用while的时候,用 int  index = (i + 1 )% cost.size  取余来遍历,当index = i 的时候就是跑完一圈。
  2. 贪心的解法
    1. 局部最优:当前累加rest【i】的和curSum一旦小于0,起始位置至少要是i+1,要是后面还有小于0,继续更新起始位置 i+1。
    2. 全局最优:找到可以跑一圈的起始位置
    3. 局部最优可以推出全局最优,找不出反例,试试贪心。

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int length = gas.length;

        int curSum = 0;     //记录从i位置开始的油量是否为负
        int totalSum = 0;  //总油量,当总油量为负的时候直接返回-1
        int index = 0;     //需要返回的位置,curSum为负时需要更新这个位置

        for(int i=0; i<length; i++){
            curSum += gas[i] - cost[i];
            totalSum += gas[i] - cost[i];

            if(curSum < 0){
                curSum = 0;
                index = i+1;
            }

        }

        if(totalSum < 0)
            return -1;

        return index;

    }
}


力扣题目 135.分发糖果

思路

  1. 当遇到这样类似的比较题目,不要两边同时比较,应该先比较一边,再比较另一边。
  2. 、从哪边开始比较,应该从哪边开始遍历顺序 

class Solution {
    public int candy(int[] ratings) {
        int length = ratings.length;
        int[] candy = new int[length];
        int sum = 0;

        //先从左到右遍历
        //又因为在循环里面i直接从1开始遍历,所以当i为0的时候就需要初始值
        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;
        }

        sum += candy[length-1];

        //从右到左遍历
        for(int i = length-2; i>=0; i--){
            if(ratings[i] > ratings[i+1])
                candy[i] = Math.max(candy[i], candy[i+1]+1);
            
            //当右边比左边大的时候,也是求最大值,但是可以留有原来的值

            //总和
            sum += candy[i];
        }

        return sum;
    }
}

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值