🚩传送门:牛客题目

题目

给你一个长度为 [NC]148. 几步可以从头跳到尾 - 图1 的数组 [NC]148. 几步可以从头跳到尾 - 图2 [NC]148. 几步可以从头跳到尾 - 图3 表示从 [NC]148. 几步可以从头跳到尾 - 图4 这个位置开始最多能往后跳多少格 。求从 [NC]148. 几步可以从头跳到尾 - 图5 开始最少需要跳几次就能到达第 [NC]148. 几步可以从头跳到尾 - 图6 个格子 。
进阶: 空间复杂度 [NC]148. 几步可以从头跳到尾 - 图7 , 时间复杂度 [NC]148. 几步可以从头跳到尾 - 图8

示例1:

输入:2,[1,2] 返回值:1 说明:从 1 号格子只需要跳跃一次就能到达 2 号格子

示例2:

输入:3,[2,3,1] 返回值:1 说明:从 1 号格子只需要跳一次就能直接抵达 3 号格子

解题思路:双指针

参数说明:

  • _left_[NC]148. 几步可以从头跳到尾 - 图9[NC]148. 几步可以从头跳到尾 - 图10的边界
  • _right_[NC]148. 几步可以从头跳到尾 - 图11的最右端边界
  • _res:_保存需要返回的答案
  • _[i,left]_ 区间的步长需要 [NC]148. 几步可以从头跳到尾 - 图12
  • _[left,right]_ 区间的步长需要 [NC]148. 几步可以从头跳到尾 - 图13

算法说明:

初始化内容:[NC]148. 几步可以从头跳到尾 - 图14 [NC]148. 几步可以从头跳到尾 - 图15 [NC]148. 几步可以从头跳到尾 - 图16

image.png
指针**i****0** 开始遍历至数组结尾。并查看自身当前位置所能跳到的最远距离(i+A[i]),看是否能刷新 [NC]148. 几步可以从头跳到尾 - 图18

  • 不能刷新,则i继续遍历下一个位置
  • 若能刷新,则查看当前 ileft 的左边还是右边
    • 左边:是说明跳跃到的地方所需步长依旧为 [NC]148. 几步可以从头跳到尾 - 图19 ,仅需要修改 [NC]148. 几步可以从头跳到尾 - 图20 指向最远边界即可
    • 右边:是说明跳跃到的地方所需步长更改[NC]148. 几步可以从头跳到尾 - 图21 ,此时需要修改 res,left,right

      [NC]148. 几步可以从头跳到尾 - 图22 [NC]148. 几步可以从头跳到尾 - 图23 **[NC]148. 几步可以从头跳到尾 - 图24

图解说明:

  1. 若不能刷新,无需任何操作,直接遍历查看下一个位置

image.png

  1. 若能刷新,则查看当前 ileft 的左边还是右边

image.png
image.png

复杂度分析

时间复杂度: [NC]148. 几步可以从头跳到尾 - 图28 ,该方法需要遍历一次数组所有元素 。

空间复杂度:[NC]148. 几步可以从头跳到尾 - 图29 ,该方法使用常数空间 。

我的代码

  1. public int Jump (int n, int[] A) {
  2. int left=0,right=A[0],res=0; //1. 初始化
  3. if(A[0]>n) return 1;
  4. for(int i=0;i<A.length;i++){
  5. if(i+A[i]>right){ //2. 可刷新
  6. if(i>left){ //3. i在left左侧
  7. res++;
  8. left=right;
  9. right=i+A[i];
  10. }else{ //4. i在left右侧
  11. right=i+A[i];
  12. }
  13. }
  14. }
  15. return res;
  16. }