Question
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
For example:
Given array A = [2,3,1,1,4]
The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)
本题难度Hard。有2种算法分别是: 双指针法(推荐)和BFS(超时)
【注意】
本题对时间要求特别严格。
1、双指针法
【复杂度】
时间 O(N) 空间 O(1)
【思路】
用两个指针指出一块当前结点能跳的上下边界,然后再对这块区域遍历,找出这块区域能跳到的下一块区域的上下边界,每块区域都对应一步,直到上界超过终点时为之。
【代码】
public class Solution {
public int jump(int[] nums) {
//require
if(nums==null)
return 0;
int size=nums.length;
if(size<=1)
return 0;
//invariant
int step=0,preHigh=0,high=0,low=0;
while(high<size-1){
step++;
preHigh=high;
for(int i=low;i<=preHigh;i++)
high=Math.max(i+nums[i],high);
low=preHigh+1;
}
//ensure
return step;
}
}
2、BFS
【复杂度】
时间 O(N) 空间 O(N)
【思路】
广度优先搜索。可以解决该问题,不过超时。原因在于需要判断节点上一步是否已经搜索过(双指针法就不需要),耗费了时间。
实际上BFS更适合于图的路径搜索(而双指针法就解决不了)。
【代码】
public class Solution {
public int jump(int[] nums) {
//require
if(nums==null)
return 0;
int size=nums.length;
if(size<=1)
return 0;
//initialize queue
Set<Integer> set=new HashSet<Integer>();
Queue<Element> q=new LinkedList<Element>();
q.offer(new Element(0,0));
set.add(0);
//invariant
while(!q.isEmpty()){
Element e=q.poll();
if(e.index+nums[e.index]>=size-1)
return e.step+1;
for(int i=1;i<=nums[e.index]&&i+e.index<size;i++){
if(!set.contains(e.index+i)){
q.offer(new Element(e.step+1,e.index+i));
set.add(e.index+i);
}
}
}
return 0;
}
class Element{
int step=-1;
int index=-1;
public Element(int step,int index){
this.step=step;
this.index=index;
}
}
}
参考
[Leetcode] Jump Game 跳跃游戏