LeetCode 55. 跳跃游戏
贪心:
1.贪心+正序
对于数组中的任意一个位置y,如何判断它是否可以到达?根据题目描述,只要存在一个位置x,它本身可以到达,而且它跳跃的最大长度为nums[x],那么x+nums[x],如果x+nums[x]>=y,那么位置y也可以到达。
也就是说,对于每一个可到达的位置x,它使得x+1,x+2,… ,x+nums[x]>=y,那么位置y也可以到达。
这样依次遍历数组中的每一个位置,并实时维护可以到达的最远位置。对于当前到达的位置x,如果它在最远可以到达的位置的范围内,那么我们可以从起点通过若干次跳跃到达该位置,因此我们可以用x+nums[x]来更新最远到达的位置。
在遍历的过程中,如果最后一个位置可达,直接返回true作为答案。反之,如果在遍历结束后,仍不可达,那么返回false作为答案。
class Solution {
public:
bool canJump(vector<int>& nums) {
int n=nums.size(), reach=0;
for(int i=0;i<n;i++){
if(i<=reach){
reach=max(reach,i+nums[i]);
if(reach>=n-1) return true;
}
}
return false;
}
};
2.贪心+逆序
class Solution {
public:
bool canJump(vector<int>& nums) {
int n=nums.size(),last=n-1;
for(int i=n-2;i>=0;i--){
if(i+nums[i]>=last)
last=i;
}
return last==0;
}
};
LeetCode 45. 跳跃游戏 II
在上一题的基础上有所改编,问使用最少的跳跃次数到达数组的最后一个位置。
思想就一句话:每次在上次能跳到的范围(end)内选择一个能跳的最远的位置作为下次的起点。
不过我不明白为啥可以这样???discuss区中有所证明,但是没懂,以后有机会再来搞懂。
class Solution {
public:
int jump(vector<int>& nums) {
//end 上次跳跃可达范围右边界(下次的最右起跳点)
int maxPos=0,n=nums.size(),end=0,step=0;
for(int i=0;i<n-1;++i){
maxPos=max(maxPos,i+nums[i]);
//到达上次跳跃能到达的右边界了
if(i==end){//i到达起跳位置
//下次起跳位置设置为本次贪心得到的最远距离
end=maxPos;
++step;
}
}
return step;
}
};