代码随想录 day32 第八章 贪心算法 part02

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

●  55. 跳跃游戏

●  45.跳跃游戏II

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

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

  • 思路

    • 局部最优:
      • 只收获每天的正利润
    • 全局最优
      • 局部最优累计的最大利润
    • 当天卖了还可以用当天的价格买入
  • 题解

    func maxProfit(prices []int) int {
    	res := 0
    	// 从第二天开始计数, 当天加个高于前天就收获利润
    	for i := 1; i < len(prices); i++ {
    		if prices[i]-prices[i-1] > 0 {
    			res += prices[i] - prices[i-1]
    		}
    	}
    
    	return res
    }
    

55. 跳跃游戏

关联 leetcode 55. 跳跃游戏

  • 思路

    • 使用覆盖范围来判断是否能跳到最后一个格子
      • 累加当前能跳到的所有格子的覆盖范围,取最大值
  • 题解

    func canJump(nums []int) bool {
    	if len(nums) < 2 {
    		return true
    	}
    	cover := 0
    	end := len(nums) - 1
    	// 从起点到当前当前已覆盖的范围内, 逐步遍历, 累计覆盖范围
    	for i := 0; i <= cover; i++ {
    
    		if i+nums[i] > cover { //当前位置能跳到的最远距离比当前覆盖范围大, 更新覆盖范围
    			cover = i + nums[i]
    		}
    		if cover >= end { //走到最后一个位置
    			return true
    		}
    	}
    	return false
    }
    

45.跳跃游戏II

关联 leetcode 45.跳跃游戏II

  • 思路
    • 依然从覆盖范围思考出发
    • 在覆盖范围内,以最小的步数增加覆盖范围,当覆盖范围包含了终点就是最小步数
      • 统计两个覆盖范围,当前这步的最大覆盖下一步的最大覆盖
        • 当前这步的最大覆盖
          • 当前 数组的【索引】值
        • 下一步的最大覆盖
          • 当前范围内最大索引值
  • 题解
    • 方法一

      • 移动下标达到了当前覆盖的最远距离下标时,步数就要加一,来增加覆盖距离。最后的步数就是最少步数。
        • 这里还是有个特殊情况需要考虑,当移动下标达到了当前覆盖的最远距离下标时
        • 如果当前覆盖最远距离下标不是是集合终点,步数就加一,还需要继续走。
        • 如果当前覆盖最远距离下标就是是集合终点,步数不用加一,因为不能再往后走了。
      func jump(nums []int) int {
      	if len(nums) < 2 {
      		return 0
      	}
      	step := 0 //移动的步数
      	curDistance := 0
      	nextDistance := 0
      	for i := 0; i < len(nums); i++ {
      		nextDistance = max(nums[i]+i, nextDistance) //更新下一步最远覆盖距离
      		if i == curDistance {                       //到达本次最远覆盖距离
      			// 此时 i < len(nums) 即 curDistance < len(nums), 还没有走到末尾, 需要继续往前走
      			step++
      			curDistance = nextDistance       // 更新当前覆盖最远距离下标(相当于加油了)
      			if nextDistance >= len(nums)-1 { //这里用  len(nums)-1 的原因: 走的是索引从0开始
      				break
      			}
      		}
      	}
      	return step
      }
      
      func max(a, b int) int {
      	if a > b {
      		return a
      	}
      	return b
      }
      
      • 方法二

        • 针对于方法一的特殊情况,可以统一处理,即:移动下标只要遇到当前覆盖最远距离的下标,直接步数加一,不考虑是不是终点的情况。
        • 想要达到这样的效果,只要让移动下标,最大只能移动到 nums.size - 2 的地方[倒数第二个数,最终能走一步的地方]就可以了。
        • 因为当移动下标指向 nums.size - 2 时:
          • 如果移动下标等于当前覆盖最大距离下标, 需要再走一步(即 ans++),因为最后一步一定是可以到的终点【题目要求】
        func jump(nums []int) int {
        
        	step := 0
        	curDistance := 0
        	nextDistance := 0
        	for i := 0; i < len(nums)-1; i++ {
        		nextDistance = max(nums[i]+i, nextDistance)
        		if i == curDistance {
        			curDistance = nextDistance
        			step++
        		}
        	}
        	return step
        }
        
        func max(a, b int) int {
        	if a >= b {
        		return a
        	}
        	return b
        }
        

  • 32
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值