Skip to content

55 Jump Game

又可以贪心,也可以dp.

  • 贪心的思路更加直观,也更加容易理解, 但怎么证明很难.
  • dp的思路,更加严谨,但由于dp也是一种枚举, 同时记忆以前的子问题,所以会有更多的空间复杂度.

Approach 1 Greedy

有一个数组,里面的数字代表了可以跳的最大步数,问是否能够跳到最后一个位置,nums = [2,3,1,1,4], 也就是说:

  • index i: 表达目前在的位置index.
  • nums[i]: 表达这个位置能走的最大步数, 1,2,...,nums[i]

我们每一步的行走,可以看作一个子问题。每一个子问题的最优解,用贪心的策略,就是"最有潜力的那一步", 你可以定义为

  • 能到达的最远距离: step + nums[step]
  • 能走出的最大一步: (step - i) + nums[step]

以上这两种都是一样的,而step的选择范围,是要看nums[i], 为[1,2,...,nums[i]].

我们做一下dry run, nums = [2,3,1,1,4],

we currently at index 0, we can go max 2 steps. No point go 0 step
- we go 1 step, we can then go max 3 steps. Potential is 4
- we go 2 steps, we can then go max 1 steps. Potential is 3

we greedily choose 1 step, because it has the most potential.

Code Implementation

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        # brute force: try out every combination
        # (0,2) --> 1 step or 2 step
        """(i,nums[i])
                (0,2)
            (1,3)   (2,1)
                    (3,1)
                    (4,4)
        """
        # Or 当前的最优解 = index + it's value

        # base case
        n = len(nums)
        if n == 1:
            return True

        curr = 0

        while curr <= n:
            best = 0
            best_index = curr
            for step in range(1,nums[curr]+1):
                new_curr = curr + step
                if new_curr >= n-1:
                    return True
                if new_curr + nums[new_curr] > best:
                    best = new_curr + nums[new_curr]
                    best_index = new_curr                    
            # if not updating, it means, 
            if best == 0:
                return False

            # move curr pointer by that much
            curr = best_index

Approach 2 DP

complexity

  • time: O(n^k) where n is the length of the array and k is 最大值域.
  • space: O(n)
class Solution:
    def canJump(self, nums: List[int]) -> bool:
        """
        倒着来走一遍,
        dp[i]: 能否从index i 跳到终点index n-1
        初始条件:
        dp[n-1] = 1
        state transition function:

        """
        n = len(nums)
        # initialize 
        dp = [False] * n
        dp[n - 1] = True

        for idx in range(n - 2, -1, -1):
            if nums[idx] == 0:
                # 这一步的数值为0,没法走了
                dp[idx] = False
                continue

            # 当前index能走的最远距离
            reach = idx + nums[idx]
            for jump in range(idx + 1, reach + 1):
                # 没跳出界,或者跳到的这一步(jump)为True.
                # jump --> destination, 而idx --> jump, 那我们就可以到终点from idx
                if jump < len(nums) and dp[jump]:
                    dp[idx] = True
                    break

        return dp[0]

Reference