夸父追日:第八章 贪心算法 part02

今日收获:买卖股票的最佳时机II,跳跃游戏,跳跃游戏Ⅱ,K次取反后最大化的数组和

1. 买卖股票的最佳时机II

题目链接:122. 买卖股票的最佳时机 II - 力扣(LeetCode)

思路:收集每天的正利润(局部最优),如果这天亏了就不收集。重点是有一个思路上的转变,将最低买入和最高卖出,转化为收集每一天的利润。

方法:

class Solution {
    public int maxProfit(int[] prices) {
        int max=0;
        int len=prices.length;

        for (int i=1;i<len;i++){
            if ((prices[i]-prices[i-1])>0){
                max+=prices[i]-prices[i-1];
            }
        }
        return max;
    }
}

2. 跳跃游戏

题目链接:55. 跳跃游戏 - 力扣(LeetCode)

思路:将每一个元素的位置和元素值相加就是本位置能达到的最大覆盖范围(局部最优),不断更新最大覆盖范围,判断覆盖范围能不能到达终点(全局最优)。注意只能在覆盖范围中跳跃,即覆盖范围就是循环的终止条件。

 方法:

class Solution {
    public boolean canJump(int[] nums) {
        int cover=0;
        int len=nums.length;

        for (int i=0;i<=cover;i++){
            cover=Math.max(i+nums[i],cover);  // 覆盖范围
            
            if (cover>=(len-1)){
                return true;
            }
        }
        return false;
    }
}

3. 跳跃游戏Ⅱ

题目链接:45. 跳跃游戏 II - 力扣(LeetCode)

思路:每一步都尽可能求最大的覆盖范围(局部最优)。如果当前步中的最大覆盖范围都没有到达终点(此时走到了当前步覆盖范围的尽头),就将最大覆盖范围作为当前步的覆盖范围,此时步数再加1。

方法:

class Solution {
    public int jump(int[] nums) {
        int count=0;
        int curCover=0; // 处在0的位置肯定要跳一步,除非长度为0
        int maxCover=0;

        if (nums.length==1){
            return 0;
        }

        for (int i=0;i<nums.length;i++){
            maxCover=Math.max(maxCover,i+nums[i]);

            // 差最后一步可以跳到终点
            if (maxCover>=(nums.length-1)){
                count++;
                break;
            }

            if (i==curCover){  // 最大覆盖范围还不到,就要再跳
                curCover=maxCover;
                count++;             
            }
        }

        return count;
    }
}

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

题目链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)

思路:先将k尽可能作用于较大的负数反转(一次贪心),如果还有剩余,就全部作用在最小的正数上(两次贪心)

方法:

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        Arrays.sort(nums);

        // 先处理负数
        for (int i=0;i<nums.length;i++){
            if (nums[i]<0&&k>0){
                nums[i]*=-1;
                k--;
            }
        }

        Arrays.sort(nums);
        // 将k作用于最小正数
        if (k>0&&k%2==1){
            nums[0]*=-1;
        }

        // 计算数组总和
        int sum=0;
        for (int i=0;i<nums.length;i++){
            sum+=nums[i];
        }

        return sum;
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值