【LeetCode】45. 跳跃游戏 II

leetcode

 

解题思路

该问题需要找到从数组起点到终点的最小跳跃次数,​贪心算法是最优解决方案。核心策略是:

  1. 局部最优:每次跳跃选择当前能覆盖的最远范围,减少后续跳跃次数。
  2. 全局最优:通过动态维护跳跃边界,确保总跳跃次数最少。

关键步骤

  1. 变量定义

    • jumps:记录跳跃次数(初始为0)。
    • currentEnd:当前跳跃能到达的最远位置(初始为0)。
    • maxFar:全局能到达的最远位置(动态更新)。
  2. 遍历与更新

    • 遍历数组,每一步更新 maxFar = max(maxFar, i + nums[i])
    • 当索引 i 到达 currentEnd 时触发跳跃,更新 currentEnd 为最新 maxFar,并增加跳跃次数。
    • 若 currentEnd 已覆盖终点(>= n-1),提前终止循环。
  3. 边界处理

    • 数组长度为1时直接返回0(无需跳跃)。
func jump(nums []int) int {
    n := len(nums)
    if n == 1 {
        return 0
    }
    jumps, currentEnd, maxFar := 0, 0, 0
    for i := 0; i < n; i++ {
        if i + nums[i] > maxFar {
            maxFar = i + nums[i]
        }
        if i == currentEnd {
            jumps++
            currentEnd = maxFar
            if currentEnd >= n-1 {
                break
            }
        }
    }
    return jumps
}

 


复杂度分析

指标说明
时间复杂度 O(n) 仅需一次线性遍历数组
空间复杂度 O(1) 仅使用常数级变量

测试用例验证

  1. 示例1

    nums := []int{2, 3, 1, 1, 4}
    fmt.Println(jump(nums)) // 输出: 2
    • 步骤解析
      • 初始 currentEnd=0maxFar=0
      • i=0: 更新 maxFar=2,触发跳跃,jumps=1currentEnd=2
      • i=1: 更新 maxFar=4
      • i=2: 到达 currentEnd=2,触发跳跃,jumps=2currentEnd=4(覆盖终点)。
  2. 示例2

    nums := []int{2, 3, 0, 1, 4}
    fmt.Println(jump(nums)) // 输出: 2
    • 步骤解析
      • 初始 currentEnd=0maxFar=0
      • i=0: 更新 maxFar=2,触发跳跃,jumps=1currentEnd=2
      • i=1: 更新 maxFar=4
      • i=2: 到达 currentEnd=2,触发跳跃,jumps=2currentEnd=4。
  3. 边界用例

    • 单元素数组
      nums := []int{5}
      fmt.Println(jump(nums)) // 输出: 0
    • 需多次跳跃
      nums := []int{1, 1, 1, 1, 1}
      fmt.Println(jump(nums)) // 输出: 4

核心逻辑总结

  1. 贪心策略优势:相比动态规划(时间复杂度 O(n²)),贪心算法通过单次遍历实现高效求解。
  2. 跳跃触发条件:到达当前边界时强制跳跃,确保每一步覆盖范围最大化。
  3. 提前终止优化:避免无效遍历,提升性能。

通过结合贪心策略与边界动态更新,该方案在保证正确性的同时达到最优时间复杂度,适用于大规模输入场景。

posted @ 2025-03-27 12:10  云隙之间  阅读(34)  评论(0)    收藏  举报