2022.04.13 力扣55,45,122

学习:贪心算法

follow:代码随想录


55 跳跃游戏

题目描述:
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标

数组中的每个元素代表你在该位置可以跳跃的最大长度

判断你是否能够到达最后一个下标

解析:
方法一:暴力求解
从最后一个位置向前看:能到达该位置的下标有哪些,并把它们加入到队列中,如果0能到达该位置,则结束。

public boolean canJump(int[] nums) {
        if(nums.length <= 1) return true;
        //队列维护要遍历的下标
        Deque<Integer> queue = new LinkedList<>();
        //标志子问题是否已经被计算过
        boolean[] flag = new boolean[nums.length];
        queue.addLast(nums.length - 1);
        while(!queue.isEmpty()){
            int index = queue.removeFirst();
            //判断该位置可以从哪些位置到达
            for(int i = 0; i < index; i++){
                if(nums[i] >= (index - i) && !flag[i]){
                    //如果0下标能到达,则结束
                    if(i == 0) return true;
                    queue.addLast(i);
                    flag[i] = true;
                }
            }
        }
        return false;
    }

方法二:
贪心算法:每次都取最大跳跃值,可得到最大跳跃覆盖范围,最终能否覆盖到终点。

 public boolean canJump(int[] nums) {
        //end表示当前的覆盖范围
        int end = 0;
        for(int i = 0; i <= end; i++){
            //扩大覆盖范围
            end = Math.max(end, i + nums[i]);
            //覆盖范围是否到达终点
            if(end >= nums.length - 1) return true;
        }
        return false;
    }
45. 跳跃游戏2⃣️

题目描述:
给你一个非负整数数组 nums ,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

解析:
方法一:动态规划

  • dp数组及其含义
    dp[i]表示从初始点最少走多少步能到达下标为i的位置
  • 确定递推公式
    从0到i-1,依次看到达i点的步数哪个最小
    dp[i] = Math.min(dp[i], dp[j] + 1);
  • 初始化
    在起点看,走0步到达第一个位置,dp[0]=0
    其他位置都是最大值
public int jump(int[] nums) {
        //dp表示从初始点最少走多少步能到达该点
        int[] dp = new int[nums.length];
        Arrays.fill(dp, Integer.MAX_VALUE);
        //初始化:在起点看,走0步
        dp[0] = 0;
        for(int i = 1; i < nums.length; i++){
            for(int j = 0; j < i; j++){
                if(nums[j] >= (i - j)){
                    dp[i] = Math.min(dp[i], dp[j] + 1);
                }
            }
        }
        return dp[nums.length - 1];
    }

方法二:贪心算法
依然是看最大覆盖范围,但是本题要求最小步数,所以要看最小步数所能覆盖的最大范围。

  • 什么时候增加步数
    当遍历到当前最大覆盖范围时,步数加一,并更新最大覆盖范围。意思是:当前最小步数,所能达到的最远距离
  • 什么时候结束
    遍历到某个位置,最远覆盖范围覆盖了最后一个位置
public int jump(int[] nums) {
        if(nums.length == 1) return 0;
        int result = 0;
        int curdis = 0;
        int fardis = 0;
        for(int i = 0; i < nums.length; i++){
            fardis = Math.max(fardis, i + nums[i]);
            //已经覆盖了最后一个位置
            if(fardis >= nums.length - 1){
                return result + 1;
            }
            //当前最小步数已经到了最远距离
            if(i == curdis){
                result++;
                curdis = fardis;
            }
        }
        return result;
    }
买卖骨片的最佳时机2⃣️

题目描述:
给定一个数组 prices ,其中 prices[i] 表示股票第 i 天的价格。

在每一天,你可能会决定购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以购买它,然后在 同一天 出售。
返回 你能获得的 最大 利润 。

解析:
本题可以用动态规划,也可以用贪心算法
贪心思想:只要第二天的价格比第一天的价格高就卖出去

public int maxProfit(int[] prices) {
        int result = 0;
        for(int i = 1; i < prices.length; i++){
            if(prices[i] > prices[i - 1]){
                result += prices[i] - prices[i - 1];
            }
        }
        return result;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值