持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
跳跃数组
给你一个非负整数数组 nums
,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。
解析
阅读完该题目我的第一想法就是使用类似“动态规划”的方法来解决,虽然确实可以用,但是效率和性能都比不上贪心算法。由于官方用的是贪心算法,我这里就不细讲贪心算法。
那么这题该怎么建立动态规划呢?我们先把该数组分解成多个子问题,举个栗子:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
对于nums[0],即 2 来说,它能够一步到达的地方的下标为{1,2},且到达下标0需要0步。
数组元素 | 2 | 3 | 1 | 1 | 4 |
---|---|---|---|---|---|
下标位置 | 0 | 1 | 2 | 3 | 4 |
所需步数 | * | 1 | 1 |
对于nums[1],它能够一步到达的地方的下标为{2,3,4},且到达下标1根据上一步我们知道需要1步, 所以通过nums[1]到达{2,3,4}需要2步。但是我们发现,到达下标2的位置,我们从nums[0]一步就能到了,不需要通过nums[1]的中转站,所以可得下列表格。
数组元素 | 2 | 3 | 1 | 1 | 4 |
---|---|---|---|---|---|
下标位置 | 0 | 1 | 2 | 3 | 4 |
所需步数 | * | 1 | 1 | 2 | 2 |
对于nums[2],它能够一步到达的地方的下标为{3},发现它通过nums[1]到达下标3只需要2步,而通过nums[2]需要3步,所以可以得到下列表格
数组元素 | 2 | 3 | 1 | 1 | 4 |
---|---|---|---|---|---|
下标位置 | 0 | 1 | 2 | 3 | 4 |
所需步数 | * | 1 | 1 | 2 | 2 |
对于nums[3]来说,它是倒数第二个数组元素了,同时也是最后一个需要计算的数组元素,它能够到达的只有数组最后一个元素。发现到达下标4总共需要3步,同时发现发现它通过nums[1]到达下标4只需要2步,所以可以得到最终的表格:
数组元素 | 2 | 3 | 1 | 1 | 4 |
---|---|---|---|---|---|
下标位置 | 0 | 1 | 2 | 3 | 4 |
所需步数 | * | 1 | 1 | 2 | 2 |
代码
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];
}
}