题目难度:中等
默认优化目标:最小化平均时间复杂度。
Python默认为Python3。
目录
1 题目描述
给你一个非负整数数组 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 , 所以永远不可能到达最后一个下标。
提示:
-
1 <= nums.length <= 104
-
0 <= nums[i] <= 105
2 题目解析
输入是一个非负整数数组nums
,输出是一个bool
值(判断你是否能够到达最后一个下标,如果可以,返回 true
;否则,返回 false
)。约束条件是所处下标的元素值代表能跳跃的最大步长。
暴力求解,每种可能性都试一遍,平均时间复杂度O(n!),不考虑。可以用贪心。
3 算法原理及程序实现
3.1 贪心算法
根据题目描述,完整的数学表达式如下
pos[j]为第j次跳跃时的下标,[0,nums[pos[j]]]表示可跳跃的步数。因为当前跳跃的位置只与前一个状态有关,因此可以使用一个变量x代替原来的状态数组pos[j]。
根绝贪心,我们只需要判断跳跃能到的最远距离。判断起跳点是否在这个最远距离内,即
成立,y也可以到达,反之则不能。其中,x为本身能到达最后一个下标的位置,y为数组中的任一位置。
这样,我们依次遍历数组中的每一个位置,并实时更新最远可以到达的位置。对于x,如果在最远可以到达的位置范围内,那么我们可以从起点通过若干次跳跃到达该位置。所以我们可以直接使用x+nums[x]更新最远位置。
如果可以到达的最远位置大于等于数组中的最后一个位置,那就说明最后一个位置可达,返回true
。反之,返回false
。
平均时间复杂度为O(n),平均空间复杂度为O(1)。
C++程序实现
class Solution {
public:
bool canJump(vector<int>& nums) {
int n=nums.size();
int pos=0;
for(int i=0;i<n;i++){
if(i<=pos){
pos=max(pos,i+nums[i]);
if(pos>=n-1){
return true;
}
}
}
return false;
}
};
Python代码实现
class Solution:
def canJump(self, nums: List[int]) -> bool:
n,pos=len(nums),0
for i in range(n):
if i>pos:
return False
else:
pos=max(pos,i+nums[i])
if pos>=n-1:
return True