思路
贪心算法,由于可以跳的步数是一个范围,所以下一步能选的落点也是一个范围,所以我们用覆盖范围(从起点开始,可以到达的范围)来代替落点这一概念。
此问题转化为,从起点开始,覆盖范围>=终点距离(数组长度-1)
实现方法
从起点出发,对于每一个覆盖范围内的元素,都从该元素出发,更新最大覆盖范围。
所以算法实现可以概括为
从起点出发——>1.对当前节点更新范围——>2遍历到当前范围的末端(此过程中更新了基于当前范围的下一跳最大范围)——>3更新指针最大移动范围。
ps:对于后续衍生跳跃游戏II(达到目标位置最小步数)来说:每一次更新最大移动范围时,步数++,所以在2的时候检测就好了。
代码
跳跃游戏
bool canJump(vector<int>& nums) {
// 贪心算法,步数为当前节点向外最远延伸距离,然后对后续的延伸距离,继续看它们能延伸多远
int maxsize = nums[0];
int recsize = 0;
int x = 0;
if (nums.size() < 2) {
return true;
}
for (; x < maxsize && x < nums.size(); x++) {
recsize = x + nums[x] + 1;
// 这里移动距离得+1,因为上面的判断里是用的数组下标判断的,相当于在这一行再-1,也就是-2了,所以不对
if (recsize > maxsize) {
maxsize = recsize;
}
}
if (maxsize >= nums.size()) {
return true;
} else {
return false;
}
}
跳跃游戏II
int jump(vector<int>& nums) {
if(nums.size()==1){return 0;}//不用跳,头就是尾。
int recentsize = 0; // 基于当前元素的最大能达到的下标
int maxsize = nums[0]; // 最大能达到的下标
int step = 0;
for (int x = 0; x<nums.size()&&x <= maxsize; x++) { // 修改循环条件
recentsize = max(recentsize, x + nums[x]); // 更新recentsize
if (x == maxsize&&x!=0) { // 修改比较运算符
step++;
maxsize = recentsize; // 更新maxsize
}
if (maxsize+1>=nums.size()){step++;break;}
}
return step;
}