给定一个长度为 n
的 0 索引整数数组 nums
。初始位置为 nums[0]
。
每个元素 nums[i]
表示从索引 i
向前跳转的最大长度。换句话说,如果你在 nums[i]
处,你可以跳转到任意 nums[i + j]
处:
0 <= j <= nums[i]
i + j < n
返回到达 nums[n - 1]
的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]
。
输入: nums = [2,3,1,1,4] 输出: 2 解释: 跳到最后一个位置的最小跳跃数是 2。从下标为 0 跳到下标为 1 的位置,跳 1步,然后跳 3步到达数组的最后一个位置。
输入: nums = [2,3,0,1,4] 输出: 2
自己写的(利用贪心算法进行倒推)
public class Solution
{
public int Jump(int[] nums)
{
int Remaining = nums.Length - 1;
int steps = 0;
while (Remaining > 0)
{
for (int i = 0; i < Remaining; i++)
{
if (i + nums[i] >= Remaining)
{
Remaining = i;
steps++;
break;
}
}
}
return steps;
}
}
拿 [2,3,1,1,4]举例
刚开始时 Remaining剩余量为4
Remaining大于0 进入while循环中
然后走for循环 当for中i为1时 nums[1]=3
3+1 刚好等于 4 和Remaining剩余量相等 steps++; steps此时等于1
那么Remaining 等于i 即剩下的表示为剩余量
此时i为1 即Remaining等于1
再while循环 Remaining等于1大于0刚好进入
然后i等于0时 nums[0]=2 大于0 进入if语句
此时Remaining =0 step++; 此时steps等于2
再次数while时 Remaining等于0 不大于0 循环结束
输出结果2
主要是通过数组中索引的位置加上该位置的值大于等于剩余量时循环结束
但是此方法时间复杂度过高O(n2)
官方时间复杂度低的方法
如果我们「贪心」地进行正向查找,每次找到可到达的最远位置,就可以在线性时间内得到最少的跳跃次数。
例如,对于数组 [2,3,1,2,4,2,3],初始位置是下标 0,从下标 0 出发,最远可到达下标 2。下标 0 可到达的位置中,下标 1 的值是 3,从下标 1 出发可以达到更远的位置,因此第一步到达下标 1。
从下标 1 出发,最远可到达下标 4。下标 1 可到达的位置中,下标 4 的值是 4 ,从下标 4 出发可以达到更远的位置,因此第二步到达下标 4。
在具体的实现中,我们维护当前能够到达的最大下标位置,记为边界。我们从左到右遍历数组,到达边界时,更新边界并将跳跃次数增加 1。
在遍历数组时,我们不访问最后一个元素,这是因为在访问最后一个元素之前,我们的边界一定大于等于最后一个位置,否则就无法跳到最后一个位置了。如果访问最后一个元素,在边界正好为最后一个位置的情况下,我们会增加一次「不必要的跳跃次数」,因此我们不必访问最后一个元素。
class Solution {
public int jump(int[] nums) {
int length = nums.length;
int end = 0;
int maxPosition = 0;
int steps = 0;
for (int i = 0; i < length - 1; i++) {
maxPosition = Math.max(maxPosition, i + nums[i]);
if (i == end) {
end = maxPosition;
steps++;
}
}
return steps;
}
}