夯实算法-跳跃游戏

992 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情

题目:LeetCode

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

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

示例 1:

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

示例 2:

输入: nums = [3,2,1,0,4]
输出: false
解释: 无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。

提示:

  • 1 <= nums.length <= 3

解题思路

记数组长度是nn,从前往后跳,每一步,下标ii可以跳的最大长度是其元素[i][i],意思就是每一步都有若干选择,可以跳 00,也可以跳[i][i],问能否到达最后一个下标 n1n-1,很明显可以用动态规划解决。

状态转移方程是结果导向,换句话说就是要尽可能的以直接得到最终结果来定义状态。

f(i)f(i)为能否跳跃到下标为 ii 的状态,那么 f(n1)f(n-1) 就是整个问题的解。

如果从i1i−1位置跳,那么只要[i1][i−1]大于等于11,并且f(i1)f(i−1)也是TT,就能达到位置ii;同理,如果从i2i−2位置跳,只要[i2][i−2]大于等于22,并且f(i2)f(i−2)TT即可,

可得到状态转移方程: f(i)=f(j)nums[j]ij,j[0,i1]f(i)=f(j)∧nums[j]≥i−j,j∈[0,i−1]

且明显f(0)=Tf(0)=T

代码实现

public boolean canJump(int[] nums) {
    final int n = nums.length;
    boolean[] dp = new boolean[n];
    dp[0] = true;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < i; j++) {
            if (dp[j] && nums[j] >= i - j) {
                dp[i] = true;
            }
        }
    }
    return dp[n - 1];
}

复杂度分析

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n2)O(n^2)

掘金(JUEJIN)  一起分享知识, Keep Learning!