贪心:122. 买卖股票的最佳时机 II、 55. 跳跃游戏、45. 跳跃游戏 II

提示:努力生活,开心、快乐的一天


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

题目链接:122. 买卖股票的最佳时机 II

💡解题思路

  1. 贪心的关键是,最终利润可以分解
  2. 假如第 0 天买入,第 3 天卖出,那么利润为:prices[3] - prices[0]。
    相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。
    此时就是把利润分解为每天为单位的维度,而不是从 0 天到第 3 天整体去考虑!在这里插入图片描述
  3. 从图中可以发现,其实我们需要收集每天的正利润就可以,收集正利润的区间,就是股票买卖的区间,而我们只需要关注最终利润,不需要记录区间。局部最优:收集每天的正利润,全局最优:求得最大利润。

🤔遇到的问题

  1. 遍历的时候需要从第一天开始,不是从第0天开始

💻代码实现

贪心

var maxProfit = function (prices) {
    let result = 0
    for (let i = 1; i < prices.length; i++) {
        result += Math.max((prices[i] - prices[i - 1]), 0)
    }
    return result
};

🎯题目总结

不要整块的去看,而是把整体利润拆为每天的利润,只收集每天的正利润,最后稳稳的就是最大利润了

55. 跳跃游戏

题目链接:55. 跳跃游戏

💡解题思路

  1. 解题的关键:不一定非要明确一次究竟跳几步,每次取最大的跳跃步数,这个就是可以跳跃的覆盖范围。问题就转化为跳跃覆盖范围究竟可不可以覆盖到终点!
  2. 贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点
    在这里插入图片描述
  3. i 每次移动只能在 cover 的范围内移动,每移动一个元素,cover 得到该元素数值(新的覆盖范围)的补充,让 i 继续移动下去。
    而 cover 每次只取 max(该元素数值补充后的范围, cover 本身范围)。
    如果 cover 大于等于了终点下标,直接 return true 就可以了。

🤔遇到的问题

  1. for循环遍历的是cover的值,而不是数组本身

💻代码实现

贪心算法

var canJump = function(nums) {
    if (nums.length === 1) return true
    let cover = 0//跳跃的覆盖范围
    // 注意这里是小于等于cover
    for (let i = 0; i <= cover; i++){
        cover = Math.max(i + nums[i], cover)
        // 说明可以覆盖到终点了
        if (cover >= nums.length - 1) {
            return true
        }
    }
    return false
};

🎯题目总结

这道题目关键点在于:不用拘泥于每次究竟跳几步,而是看覆盖范围,覆盖范围内一定是可以跳过来的,不用管是怎么跳的。


45. 跳跃游戏 II

题目链接:45. 跳跃游戏 II

💡解题思路

  1. 贪心的思路,局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。整体最优:一步尽可能多走,从而达到最少步数。
  2. 从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最少步数!
    这里需要统计两个覆盖范围,当前这一步的最大覆盖和下一步最大覆盖。
    如果移动下标达到了当前这一步的最大覆盖最远距离了,还没有到终点的话,那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点。
    在这里插入图片描述

🤔遇到的问题

for循环如果i<nums.length,需要加一步判断if (nextDistance >= nums.size() - 1) break;
如果i < nums.length-1,则不需要该步

💻代码实现

贪心算法

var jump = function(nums) {
    let curIndex = 0// 当前覆盖最远距离下标
    let nextIndex = 0// 下一步覆盖最远距离下标
    let step = 0// 记录走的最大步数
    for (let i = 0; i < nums.length-1; i++){
        nextIndex = Math.max(i + nums[i], nextIndex)// 更新下一步覆盖最远距离下标
        if (i === curIndex) {// 遇到当前覆盖最远距离下标
            curIndex = nextIndex// 更新当前覆盖最远距离下标
            step++
        }
    }
    return step
};

🎯题目总结

理解本题的关键在于:以最小的步数增加最大的覆盖范围,直到覆盖范围覆盖了终点,这个范围内最少步数一定可以跳到,不用管具体是怎么跳的,不纠结于一步究竟跳一个单位还是两个单位
另外循坏的终止条件也需要注意

🎈今日心得

贪心算法今天的题,代码虽然简单,但思路确实很难独立想到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值