Teaching Kids Programming – One-way Jump Game via Backtracking, DP and Greedy Algorithm | Algorithms, Blockchain and Cloud (helloacm.com)

are given an integer array nums. You are initially positioned at the array’s first index, and each element in the array represents your maximum jump length at that position.

Return true if you can reach the last index, or false otherwise.

Example 1:
Input: nums = [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.

Example 2:
Input: nums = [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum jump length is 0, which makes it impossible to reach the last index.

Constraints:
1 <= nums.length <= 10^4
0 <= nums[i] <= 10^5

第i个位置的值表示,可以跳的最大值,即可以跳的步数是小于等于numbs[i]的。

1, 贪心

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        # Greedy O(N)
        i, n = 0, len(nums)
        reach = 0
        while i < n and i <= reach:
            reach = max(reach, nums[i] + i)
            i += 1
        return reach >= n - 1        

因为reach表示最大跳到的地方。根据题意,nums[i]表示最多可以跳的个数。那就是说,比最远近的地方,肯定都能跳到。再遍历所有近的元素(它们都可以到达)能到达的最远点。酷

2,自底向上 从dp[n]开始算,一直推到dp[0]的值,就是结果。递推就是自底向上?????

dp[i]表示能从i到终点。dp[-1]=true,最后一个就是终点。然后看 dp[-2]是否可达,依次类推。直到dp[0]是true。

如果i能到j。那么如果dp[j]已经是true(表示可以到终点),那么dp[i]肯定也是true了。

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        # Bottom-up Dynamic Programming
        # O(N^2)
        n = len(nums)
        dp = [False] * n
        dp[-1] = [True]
        for i in range(n - 2, -1, -1):
            reach = min(i + nums[i], n - 1)
            for j in range(i + 1, reach + 1):
                if dp[j]:
                    dp[i] = True
                    break
        return dp[0]

 

3,自顶向下 (递归加缓存,我们叫它为自顶向下动归)从第0个开始算,推到最终第n个。

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        n = len(nums)
        # DFS with memoization O(N^2) = Top Down Dynamic Programming       
        @cache
        def dfs(j):
            if j >= n - 1:
                return True
            for i in range(1, nums[j] + 1):
                if j + i >= n:
                    break
                if dfs(j + i):
                    return True
            return False
        return dfs(0)

4,回溯  和上面区别是去掉了缓存 @cache

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        n = len(nums)
        # Backtracking O(2^N)
        def dfs(j):
            if j >= n - 1:
                return True
            for i in range(1, nums[j] + 1):
                if j + i >= n:
                    break
                if dfs(j + i):
                    return True
            return False
        return dfs(0)

a