题意整理

  • 给定一个数组A。
  • 如果A数组中索引i对应值为t,说明可以从i处往后跳t步。
  • 求从1出发跳到n,至少需要跳几次

方法一(从后往前贪心)

1.解题思路

基本思路是从后往前找能到达目标格子的前一个格子,然后在所有满足条件的格子中选择一个尽可能靠前的格子(贪心),找到之后,立即跟新目标格子的位置,并将步数加一,终止内层循环。

2.代码实现

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 最少需要跳跃几次能跳到末尾
     * @param n int整型 数组A的长度
     * @param A int整型一维数组 数组A
     * @return int整型
     */
    public int Jump (int n, int[] A) {

        //初始化目标格子和步数
        int pos=n-1,steps=0;
        while(pos>0){
            //从前往后找能一步到pos的位置,找到就跳出循环
            for(int i=0;i<n;i++){
                if(i+A[i]>=pos){
                    //跟新目标格子pos,并将步数加一
                    pos=i;
                    steps++;
                    break;
                }
            }
        }
        return steps;
    }
}

3.复杂度分析

  • 时间复杂度:最坏情况下,循环体需要执行图片说明 次,所以时间复杂度是图片说明
  • 空间复杂度:需要额外常数级别的内存空间,所以空间复杂度为图片说明

方法二(动态规划+贪心)

1.解题思路

  • 初始化:定义一个长度为n+1的dp数组。
  • 状态定义:图片说明 表示到达第i个格子至少需要的步数。
  • 状态转移:为了到达i个格子步数最少,首先要确定前一个格子(记为j)在哪,可以通过贪心的方式找到j的位置,然后转移方程为图片说明 ,即从j位置往前再跳一次就到i位置。

动图展示:
图片说明

2.代码实现

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 最少需要跳跃几次能跳到末尾
     * @param n int整型 数组A的长度
     * @param A int整型一维数组 数组A
     * @return int整型
     */
    public int Jump (int n, int[] A) {

        //初始化dp数组,dp[i]表示到达第i个格子至少需要的步数
        int[] dp=new int[n+1];
        for(int i=2,j=1;i<=n;i++){
            //贪心地寻找到达第i个格子的前一步所在格子j
            while(j+A[j-1]<i){
                j++;
            }
            //从j位置跳一步到达i位置
            dp[i]=dp[j]+1;
        }
        return dp[n];
    }
}

3.复杂度分析

  • 时间复杂度:在循环体中,每次i指针移动,j指针也会朝着i指针方向移动到附近的位置,从而最后j最多移动了n-1次,所以时间复杂度为图片说明
  • 空间复杂度:需要额外大小为n+1的dp数组,所以空间复杂度为图片说明

方法三(从前往后贪心)

1.解题思路

首先计算当前最远可到达位置(记为cur),如果当前位置i已经在上一个最远可到达位置(pre),说明下一步一定能够到达cur,此时steps加一,同时跟新pre的值。

2.代码实现

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 最少需要跳跃几次能跳到末尾
     * @param n int整型 数组A的长度
     * @param A int整型一维数组 数组A
     * @return int整型
     */
    public int Jump (int n, int[] A) {

        //前一个最远可到达位置
        int pre=0;
        //当前最远可到达位置
        int cur=0;
        //步数
        int steps=0;
        //因为在pre处steps就加一,所以循环只需执行到索引n-2处
        for(int i=0;i<n-1;i++){
            cur=Math.max(cur,i+A[i]);
            //如果到达前一个最远可到达位置,说明下一步就可以到当前目标位置
            if(i==pre){
                pre=cur;
                steps++;
            }
        }
        return steps;
    }
}

3.复杂度分析

  • 时间复杂度:只需一层循环,所以时间复杂度为图片说明
  • 空间复杂度:需要额外常数级别的内存空间,所以空间复杂度为图片说明