思路:
首先理解题意:从首位置跳最少多少次到达末尾。
第一种:使用递归,将所有跳转路径都获取到进行求出最小值。
第二种:使用动态规划,下一次最优取决上一次的最优解
第三针:贪心,局部最优导致全局最优。也就是在0-i上最远可以跳多远j,那么在0-j上可达,在0-j上最远可以跳多远。以此类推,最终得出最少次数。每次都求的最少次数,导致全部加起来也是最少次数。
代码如下:
class Solution {
public static int jump01(int[] nums) {
if (nums==null||nums.length==0){
return 0;
}
return process(nums,0,nums.length);
}
private static int process(int[] nums, int index, int N) {
if (index>=N-1){
return 0;
}
int num = nums[index];
int minSteps = Integer.MAX_VALUE;
//如果num==0 那么无法进for循环直接返回 Integer.MAX_VALUE
for (int i = 1; i <=num; i++) {
int steps = process(nums, index + i, N);
// 只有当steps不为Integer.MAX_VALUE时,才考虑将其加入最小步数的计算
if (steps != Integer.MAX_VALUE) {
minSteps = Math.min(minSteps, 1 + steps);
}
}
return minSteps;
}
public static int jump02(int[] nums) {
if (nums==null||nums.length==0){
return 0;
}
int N=nums.length;
int[] dp = new int[N];
//0...i 上最小需要跳几步
dp[0]=0;
for (int i = 0; i < N-1; i++) {
int num = nums[i];
int index = i + num;
if (index>=N){
index=N-1;
}
for (int j =i+1; j <=index; j++) {
if (dp[j]!=0){
dp[j]=Math.min(dp[j],dp[i]+1);
}else {
dp[j]=dp[i]+1;
}
}
}
return dp[N-1];
}
public static int jump(int[] nums) {
int jumps = 0, farthest = 0, end = 0;
// 注意这里是遍历到 nums.length - 1,因为我们到达最后一个元素时不需要再跳跃
for (int i = 0; i < nums.length - 1; i++) {
// 更新能够到达的最远位置
farthest = Math.max(farthest, i + nums[i]);
// 当到达上一跳能到达的边界时
if (i == end) {
jumps++; // 增加跳跃次数
end = farthest; // 更新下一跳能到达的边界
if (end >= nums.length - 1) { // 如果已经能够到达或超过最后一个位置,则结束循环
break;
}
}
}
return jumps;
}
}