返回

跳出思维框架,尽享LeetCode 45 跳跃游戏 II的挑战!

闲谈

LeetCode 45 跳跃游戏 II:寻觅最优跳跃路径

导语

跳跃游戏 II 是 LeetCode 上一道广受欢迎的算法题,旨在考察你的动态规划能力。它要求你从数组的起点出发,利用数组中每个元素所代表的最大跳跃距离,以最少的跳跃次数到达数组的终点。这道题不仅考验你的算法功底,更需要你具备缜密的思维逻辑和对问题深入剖析的能力。

题目

给你一个非负整数数组 nums,表示你在数组的每个位置可以跳跃的最大长度。你的目标是找到从数组的起点跳到终点的最少跳跃次数。如果不能到达终点,则返回 -1。

示例:

输入:[2,3,1,1,4]
输出:2
解释:从起点跳到终点最少需要 2 次跳跃。
第一步:从起点跳到下标为 1 的位置,跳跃距离为 2。
第二步:从下标为 1 的位置跳到下标为 4 的位置,跳跃距离为 3。

解题思路:动态规划

动态规划是一种经典的算法设计范式,常用于解决具有最优子结构性质的问题。跳跃游戏 II 正是这样一道典型的动态规划问题。它的最优子结构性质体现在以下几点:

  1. 最优子问题: 求解从任意位置跳到终点的最少跳跃次数。
  2. 重叠子问题: 从某个位置跳到终点的最少跳跃次数可以由其相邻位置的最少跳跃次数推导出。
  3. 最优子结构: 从某个位置跳到终点的最少跳跃次数等于从其相邻位置跳到终点的最少跳跃次数加 1。

解题步骤:

  1. 定义状态: dp[i] 表示从位置 i 跳到终点的最少跳跃次数。
  2. 初始化: 将 dp[n-1] 设置为 0,表示从终点跳到终点的最少跳跃次数为 0。
  3. 状态转移方程: 对于位置 i,如果 i + nums[i] >= n-1,则 dp[i] = min(dp[i], dp[i+1], ..., dp[i+nums[i]]) + 1。否则,dp[i] = 无穷大。
  4. 计算结果: 从位置 0 开始,依次计算每个位置的 dp 值,直到计算出 dp[0]。dp[0] 即为从起点跳到终点的最少跳跃次数。

时间复杂度: O(n^2),其中 n 为数组的长度。

空间复杂度: O(n),其中 n 为数组的长度。

代码实现:

def jump(nums):
    n = len(nums)
    dp = [float('inf')] * n

    # 初始化
    dp[n-1] = 0

    # 状态转移
    for i in range(n-2, -1, -1):
        for j in range(i+1, min(i+nums[i]+1, n)):
            dp[i] = min(dp[i], dp[j] + 1)

    # 返回结果
    return dp[0] if dp[0] != float('inf') else -1

结语

跳跃游戏 II 是一道颇具挑战性的算法题,但通过动态规划这一利器,我们可以轻松将其攻克。这道题不仅考验我们的算法功底,也启发我们从更广阔的视角去思考问题,寻找解决问题的最优方案。希望这篇文章对你的学习有所帮助,也希望你能够在算法的道路上越走越远!