一、题目描述
给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。
二、测试用例
示例 1:
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
示例 2:
输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
三、解题思路
- 基本思路:遍历序列,走到当前能走的最大位置,如果最大位置不是序列最后一个元素,则失败,否则,则成功;
- 具体思路:
- 模拟法:模拟跳跃的过程,定义变量 cur 和 next ,cur 表示当前能跳的最远位置,next 表示在当前能到达的最远位置中,下一跳可以到达的最远位置。遍历序列,如果 cur 超过 n-1,表示可以到达序列最后一个元素,返回 true ;否则计算 next ,如果 next 等于 cur ,表示下一跳也无法超过当前能跳到的最远位置,则永远无法达到序列最后一个元素,返回 false ;【时间复杂度为 O ( n ) \Omicron(n) O(n) 】
- 遍历法:定义变量 max 和 i,max 表示能到达的最远位置,初始为序列第一个元素的值;i 用于变量序列,初始化为 0 ;遍历序列,不断更新 max ,更新完 max,判断 i 是否等于 max ,如果相等,表示已经走到能走的最远位置,此时,如果 i 不等于 n-1 ,表示无法走到序列最后一个元素,返回 false ;否则,表示可以走到序列最后一个元素,返回 true ;【时间复杂度为 O ( n ) \Omicron(n) O(n) ,但是系数会小一点】
四、参考代码
4.1 模拟法
时间复杂度: O ( n ) \Omicron(n) O(n)
空间复杂度: O ( 1 ) \Omicron(1) O(1)
bool canJump(vector<int>& nums) {int n=nums.size();int cur,next;for(int i=0;i<n;){cur=i+nums[i];if(cur>=n-1) return true;next=cur;for(int j=i+1;j<=cur;j++){if(j+nums[j]>next){next=j+nums[j];i=j;}}if(next==cur)return false;}return true;
}
测试结果:
4.2 遍历法
时间复杂度: O ( n ) \Omicron(n) O(n)
空间复杂度: O ( 1 ) \Omicron(1) O(1)
bool canJump(vector<int>& nums) {int n=nums.size();int max=nums[0];for(int i=0;i<n;i++){max=(nums[i]+i>max)?nums[i]+i:max;if(i==max&&i!=n-1) return false;}return true;
}
测试结果