题目描述:
给定一个长度为 n
的 0 索引整数数组 nums
。初始位置为 nums[0]
。
每个元素 nums[i]
表示从索引 i
向后跳转的最大长度。换句话说,如果你在 nums[i]
处,你可以跳转到任意 nums[i + j]
处:
0 <= j <= nums[i]
i + j < n
返回到达 nums[n - 1]
的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]
。
题解:
class Solution {
public:
int jump(vector<int>& nums) {
int hop=0;//跳跃次数
int maxsize;//当前范围内最大跳数
int maxbo=0;//最大跳数下标
int maxpath=nums[0];
int n=nums.size();
if(n==1) return hop;
if(maxpath>=n-1) return hop+1;
while(1){
int k=maxbo;
maxsize=0;//出错点
for(int i=k+1;i<=maxpath;i++){//出错点
if(i+nums[i]>maxpath&&i+nums[i]>maxbo+maxsize){//出错点
maxsize=nums[i];
maxbo=i;
}
}
maxpath=maxsize+maxbo;
hop++;
if(maxpath>=n-1){
break;
}
}
return hop+1;
}
};
解题思路:
例如从第一个点开始,当前最大跳跃里程数为nums[0],设其为maxpath,在0~maxpath区间内寻找一个跳跃距离最大的点,及它是该区间内所有点中可到达距离最远的点,设该点下标为maxbo,设其nums值为maxsize,下一个考虑的区间即为maxbo~maxbo+maxsize,当前可到达的最大里程数maxpath更新为maxbo+maxsize。若maxpath>=n-1,即可到达最后一个点,反之继续考虑下一个区间。
出错点:
1.在考虑第一个区间或者下一个区间时,maxsize要初始化为0。
2.区间的考虑范围可设置为[maxbo+1,maxpath]。
3.if语句中选择条件:当前可到达的最远距离为 i+nums[i]与maxbo+maxsize、maxpath的比较!
优化题解:【贪心】
class Solution {
public:
int jump(vector<int>& nums) {
int maxpos=0;
int end=0;
int hop=0;
int n=nums.size();
for(int i=0;i<n-1;i++){
if(maxpos>=i){
maxpos=max(i+nums[i],maxpos);
if(i==end){
hop++;
end=maxpos;
}
}
}
return hop;
}
};
解题思路:
从左到右遍历数组,维护最远到达距离,记为边界,每跨越一次边界,跳跃次数加一。
出错点:
循环不必访问最后一个元素,因为在访问最后一个元素之前,我们的边界一定大于等于最后一个位置,否则就无法跳到最后一个位置了。如果访问最后一个元素,在边界正好为最后一个位置的情况下,我们会增加一次「不必要的跳跃次数」,因此我们不必访问最后一个元素。【官方解答】
优化题解:【反向查找出发位置】
class Solution {
public:
int jump(vector<int>& nums) {
int pos=nums.size()-1;
int step=0;
while(pos>0){
for(int i=0;i<pos;i++){
if(i+nums[i]>=pos){
pos=i;
break;
}
}
step++;
}
return step;
}
};
解题思路:
该方法最为简单,从后往前找上一个跳跃位置,选择距离最远的作为下一个考虑位置,即下标最小的。每找一次上一个跳跃位置即一次跳跃,直到到达第一个点。