题目
思路
其实整体还是很容易有想法的,就是跳了无数的坑…
- 贪心,大体思路就是,每次找出可跳跃范围内的最大可跳跃的步数,并记录此位置下标。以此类推,直到,跳到末尾返回true或最大可跳跃数目为0返回false。
踩坑
- 情况1:在可跳跃范围内,最大可跳跃数maxStep多次出现。最初使用max_element()求最大值仅能返回最大值出现的第一个位置,所以得自己写求maxStep的代码块。
例:第163个测试点,[5,9,3,2,1,0,2,3,3,1,0,0],如下图,第一次跳至下标1位置,此时maxStep=9,那么,第二次可跳跃的范围在2~10之间(橙色)。这个时候,若是使用max_element()则将跳到下标2位置,但最好跳到下标8位置(他们的maxStep都是3)。所以,寻找最大可跳跃数目的时候需要用“≥”以找到较靠后的那个最大可跳跃数
- 情况2:在可跳跃范围内的中间存在0。这样maxStep若出现在0的前面最好不用,重新计算maxStep
例:第164个测试用例,[4,2,0,0,1,1,4,4,4,0,4,0],如下,按上述找可跳跃范围内(1~4)的最大值,那么对于这个测试用例,将找到下标1的2值,但是,若是取下标1的2做maxStep会发现接下来都是0,根本无法跳跃。所以,对于情况,要找0后面的maxStep
代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool canJump(vector<int>& nums) {
int size=nums.size(),pos=0;
if(nums[0]==0 && size==1) return true;
if(nums[0]==0 && size>1) return false;
int step=nums[0];
int flag=0;//标识可跳跃范围内中间是否存在0
while(pos<size){
int start=pos+1, end=pos+step, maxStep=-1;
if(end>=size-1) return true;
for(int i=start;i<=end;i++){
if(flag==1&&nums[i]!=0){
maxStep=nums[i];
pos=i;
flag=0;
}
if(nums[i]>=maxStep){
maxStep=nums[i];
pos=i;
}
if(nums[i]==0) flag=1;
}
// cout<<maxStep<<" "<<pos<<endl;
if(maxStep==0 && pos<size) return false;
step=maxStep;
}
return true;
}
int main() {
int n;
cin>>n;
vector<int> nums(n);
for(int i=0;i<n;i++){
cin>>nums[i];
}
bool ret = canJump(nums);
cout<<ret<<endl;
return 0;
}