动态规划之跳跃游戏二

63 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

动态规划(Dynamic Programming)是一种分阶段求解决策问题的数学思想,它通过把原问题分解为简单的子问题来解决复杂问题。

跳跃游戏 II

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

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

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

 

示例 1:

输入: nums = [2,3,1,1,4]

输出: 2

解释: 跳到最后一个位置的最小跳跃数是 2。   从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

示例 2:

输入: nums = [2,3,0,1,4]

输出: 2

思路:

定义dp[i]为跳到下标 i 所需的最小跳跃次数,那么dp[nums.length-1]就是所求结果,如何让这个值最小呢,只需要在下标 i 位置前面找到一个下标 j ,它既可以跳到下标i,而且dp[j]最小,然后dp[i]=dp[j]+1。

由于一开始就在下标0,所以dp[0]=0。

代码如下:

fun jump(nums: IntArray): Int {
    val length = nums.size
    val dp = IntArray(length)
    Arrays.fill(dp, Int.MAX_VALUE)
    dp[0] = 0
    for (i in 0 until length) {
        for (j in 0 until i) {
            if (j + nums[j] >= i) {//1
                dp[i] = Math.min(dp[j] + 1, dp[i])//2
            }
        }
    }
    return dp[length - 1]
}
  • 注释1位置是为了保证从下标j可以跳转到下标i。
  • 注释2位置是因为可能有多个下标都可以跳转到i位置,我们只需要找到最小的跳跃次数即可。

复杂度分析

  • 时间复杂度:O(n2),n 是数组长度。有两层嵌套循环。
  • 空间复杂度:O(n),申请了dp数组。