2022.04.13 力扣55,45,122

2022.04.13 力扣55,45,122,第1张

学习:贪心算法

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;
    }

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/634595.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-16
下一篇 2022-04-16

发表评论

登录后才能评论

评论列表(0条)

保存