算法题目 -- 跳跃数组

135 阅读2分钟

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

跳跃数组

给你一个非负整数数组 nums ,你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 你的目标是使用最少的跳跃次数到达数组的最后一个位置。 假设你总是可以到达数组的最后一个位置。

解析

阅读完该题目我的第一想法就是使用类似“动态规划”的方法来解决,虽然确实可以用,但是效率和性能都比不上贪心算法。由于官方用的是贪心算法,我这里就不细讲贪心算法。

那么这题该怎么建立动态规划呢?我们先把该数组分解成多个子问题,举个栗子:

输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
     从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

对于nums[0],即 2 来说,它能够一步到达的地方的下标为{1,2},且到达下标0需要0步。

数组元素23114
下标位置01234
所需步数*11

对于nums[1],它能够一步到达的地方的下标为{2,3,4},且到达下标1根据上一步我们知道需要1步, 所以通过nums[1]到达{2,3,4}需要2步。但是我们发现,到达下标2的位置,我们从nums[0]一步就能到了,不需要通过nums[1]的中转站,所以可得下列表格。

数组元素23114
下标位置01234
所需步数*1122

对于nums[2],它能够一步到达的地方的下标为{3},发现它通过nums[1]到达下标3只需要2步,而通过nums[2]需要3步,所以可以得到下列表格

数组元素23114
下标位置01234
所需步数*1122

对于nums[3]来说,它是倒数第二个数组元素了,同时也是最后一个需要计算的数组元素,它能够到达的只有数组最后一个元素。发现到达下标4总共需要3步,同时发现发现它通过nums[1]到达下标4只需要2步,所以可以得到最终的表格:

数组元素23114
下标位置01234
所需步数*1122

代码

class Solution {
    public int jump(int[] nums) {
        int[] dps = new int[nums.length];
        for (int i = 0; i < nums.length - 1; i++) {
            //当前的值 + 1
            int jLen = Math.min(nums[i] + i, nums.length - 1);
            for (int j = i + 1; j <= jLen; j++) {
                //以前走过的步数 + 1
                if (dps[j] == 0 || dps[j] > dps[i] + 1) {
                    dps[j] = dps[i] + 1;
                }

            }
        }
        return dps[dps.length - 1];
    }
}