返回

跳跃游戏:进退无忧,畅行无阻

后端

  1. 跳跃游戏

给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可前进的最大距离。

请你判断你是否能够到达最后一个下标。

示例 1:

输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步到达下标 1 处,然后跳 3 步到达下标 4 处,最后跳 1 步到达下标 5 处。

示例 2:

输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,你总会到达下标 3 处,但无法到达下标 4 处。

动态规划解法:

  1. 定义状态:dp[i] 表示从第一个下标出发是否能到达下标 i
  2. 状态转移方程:dp[i] = dp[j] && (nums[j] >= i - j),其中 j[0, i-1] 范围内的下标。
  3. 初始状态:dp[0] = true
  4. 目标状态:dp[n-1],其中 nnums 的长度。

贪心解法:

  1. 定义变量 max_reach,表示从第一个下标出发能达到的最远下标。
  2. 遍历 nums 数组,更新 max_reachmax_reach = max(max_reach, i + nums[i])
  3. 判断 max_reach 是否大于等于 nums 的长度减一:max_reach >= nums.length - 1

代码实现:

def can_jump(nums):
  """
  :type nums: List[int]
  :rtype: bool
  """
  # 动态规划解法
  n = len(nums)
  dp = [False] * n
  dp[0] = True

  for i in range(1, n):
    for j in range(i):
      if dp[j] and nums[j] >= i - j:
        dp[i] = True
        break

  return dp[n-1]


def can_jump_greedy(nums):
  """
  :type nums: List[int]
  :rtype: bool
  """
  max_reach = 0

  for i, num in enumerate(nums):
    if i > max_reach:
      return False

    max_reach = max(max_reach, i + num)

  return max_reach >= len(nums) - 1

复杂度分析:

  • 时间复杂度:动态规划解法的时间复杂度为 O(n^2),贪心解法的时间复杂度为 O(n)
  • 空间复杂度:动态规划解法和贪心解法都使用了 O(n) 的空间。