代码随想录-2023/07/29

84 阅读2分钟

贪心算法

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

贪心法:

只要股票价格上涨就卖出

  1. 当出现1->5->4->6: 此时最大收益为5-1+6-4=6
  2. 要是一直上涨: 1->3->5->6这种呢, 你在3,5,6将其卖出是等价于你在1买入, 在6卖出的
  3. 即 3-1+5-3+6-5 == 6-1 = 5

代码:

class Solution {
    public int maxProfit(int[] prices) {
        int ans = 0;
        for(int i=0; i<prices.length-1; i++){
            if(prices[i] < prices[i+1]) {
                ans+= prices[i+1]-prices[i];
            }
        }

        return ans;
    }
}

55.跳跃游戏

贪心:

标记法

  1. 用一个标记是否可达数组is_reach, 若数组下标i为true, 代表当前位置可达, 若为false, 则代表当前位置不可达
  2. 遍历数组, 若当前位置不可达, 则代表其以后位置也永远不可达, 直接返回false
  3. 若当前位置可达, 则代表将其能达到的位置全部标记为true-可达

代码:

class Solution {
    public boolean canJump(int[] nums) {
        boolean[] is_reach = new boolean[nums.length];
        // 初始化第一个位置是可到达的
        is_reach[0] = true;
        for(int i=0; i<nums.length; i++){
            // 若当前位置可到达, 则更新其能到达的位置
            if(is_reach[i]) {
                int j = i;
                while(j <= i + nums[i] && j < nums.length){
                    is_reach[j] = true;
                    j++;
                }
            }else return false;
        }

        return true;
    }
}

45.跳跃游戏II

覆盖法:

  1. 用start 和 end 代表当前可达区间的起点和终点
  2. 若该区间达不到终点, 则代表至少需要跳出下一步
  3. 下一步的起点就是上一步的终点, 同时遍历当前区间, 找到当前步能达到的最远位置即下一步的终点

代码:

class Solution {
    // 跳跃游戏I求的是是否能达到最后一个元素
    // 跳跃游戏II求的是到达最后一个元素的最小跳跃次数
    // 跳到任意的nums[i+j]处 --- 覆盖法
    public int jump(int[] nums) {
        if(nums.length < 2) return 0;
        // 贪心法: 判断跳到下一步的最大覆盖范围
        int n = nums.length;
        // 左闭右开区间, 取得到最左边, 取不到最右边
        int start = 0, end = 1, ans = 0;
        // 当前这一步不能到达终点, 那他必须要跳出下一步
        while(end < n) {
            // 找到当前区间能跳到的最远位置
            int maxPos = 0;
            for(int i=start; i < end; i++){
                maxPos = Math.max(maxPos, i + nums[i]);
            }
            // 下一跳起跳范围开始的位置
            start = end;
            // 下一跳起跳范围结束的位置
            end = maxPos + 1;
            ans++;
        }

        return ans;
    }
}