0.题目
给你一个非负整数数组 nums ,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。
1.方法一:递归求解
这道题目主要用到 贪心算法 的思路,我们可以正向扫描数组,判断每一个位置可以走到的最远距离,当找到第一个能够覆盖到结尾的位置时就停止,这时这个位置就是我们走的最后一步的起始位置,接下来只需要把当前位置当作是倒数第二步的终点,继续进行这个步骤即可。很显然这一个过程符合递归的思路,递归的结构已经清晰,每次寻找最早能够一次到达结尾的位置,然后将这个位置作为新的终点继续寻找;递归终止条件就是终点与起点相同。
这种方法中我们选择传入一个数组,再传入一个下标来表示终点,最后一个参数用于记录步数,代码如下:
void jumps(int nums[], int end, int& cnt){
//递归终止条件,end==0
if(end ==0 )
return;
//position用于标记最早能够到达结尾的下标(倒数第二次出发点)
int position = 0;
for(int i = 0; i < end; i++){//遍历数组找到第一个可以到达结尾的点(倒数第二步出发点)
if(nums[i] + i >= end){//找到了
position = i;
cnt++;
jumps(nums, position, cnt);//递归
break;//这个break不要忘记,因为我们只找第一个能够到达的点就终止了,不用继续找
}
}
}
方法二:非递归贪心算法
递归方法比较好理解,但是时间复杂度非常高,下面方法也是贪心算法,思路是正向遍历数组,找到可达的最大距离。从数组开始进行查找,找到第一个点能够到达的最远距离,下标记为maxposition,然后我们还需要确定在当前下标到maxposition之间有没有其他节点可以到达得更远,如果有则更新maxposition,找到了真正最远距离后确定为边界end,然后步数加一视为走了一步,直到边界与当前节点重合终止。
具体代码如下:
nt jump(vector<int>& nums) {
int end = 0;
int maxp = 0;
int len = nums.size();
int cnt = 0;
for(int i = 0; i < len-1; i++){
if(maxp >= i){
maxp = max(maxp, nums[i]+i);
if(i == end){
end = maxp;
cnt++;
}
}
}
return cnt;
}