0045-跳跃游戏 II

Raphael Liu Lv10

给定一个长度为 n0 索引 整数数组 nums。初始位置为 nums[0]

每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

  • 0 <= j <= nums[i]
  • i + j < n

返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 104
  • 0 <= nums[i] <= 1000
  • 题目保证可以到达 nums[n-1]

思路

  1. 如果某一个作为 起跳点 的格子可以跳跃的距离是 3,那么表示后面 3 个格子都可以作为 起跳点

    1. 可以对每一个能作为 起跳点 的格子都尝试跳一次,把 能跳到最远的距离 不断更新。
  2. 如果从这个 起跳点 起跳叫做第 1 次 跳跃,那么从后面 3 个格子起跳 可以叫做第 2 次 跳跃

  3. 所以,当一次 跳跃 结束时,从下一个格子开始,到现在 能跳到最远的距离 是下一次 跳跃起跳点

    1. 对每一次 跳跃 用 for 循环来模拟。
    2. 跳完一次之后,更新下一次 起跳点 的范围。
    3. 在新的范围内跳,更新 能跳到最远的距离
  4. 记录 跳跃 次数,如果跳到了终点,就得到了结果。

图解

图片.png

代码

[]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int jump(vector<int> &nums)
{
int ans = 0;
int start = 0;
int end = 1;
while (end < nums.size())
{
int maxPos = 0;
for (int i = start; i < end; i++)
{
// 能跳到最远的距离
maxPos = max(maxPos, i + nums[i]);
}
start = end; // 下一次起跳点范围开始的格子
end = maxPos + 1; // 下一次起跳点范围结束的格子
ans++; // 跳跃次数
}
return ans;
}

优化

  1. 从上面代码观察发现,其实被 while 包含的 for 循环中,i 是从头跑到尾的。

  2. 只需要在一次 跳跃 完成时,更新下一次 能跳到最远的距离

  3. 并以此刻作为时机来更新 跳跃 次数。

  4. 就可以在一次 for 循环中处理。

[]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int jump(vector<int>& nums)
{
int ans = 0;
int end = 0;
int maxPos = 0;
for (int i = 0; i < nums.size() - 1; i++)
{
maxPos = max(nums[i] + i, maxPos);
if (i == end)
{
end = maxPos;
ans++;
}
}
return ans;
}

致谢

感谢您的观看,希望对您有帮助,欢迎热烈的交流!

 Comments
On this page
0045-跳跃游戏 II