题目
给定一个非负整数数组 nums
,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
示例 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 <= 3 * 104
0 <= nums[i] <= 105
解答
- 利用栈(超时)
将能到达的数组元素推进栈,模拟树的操作,但是会超时。
class Solution {
public:
bool canJump(vector<int>& nums) {
int len = nums.size();
if (len > 1 && nums[0] == 0) return false;
if (len == 1) return true;
stack<int> s; // 定义一个栈
int index = 0;
if (nums[index] > len) return true;
s.push(index);
while(!s.empty()) {
int temp_index = s.top();
int temp_num = nums[temp_index];
s.pop();
for (int i = 1; i <= temp_num; i++) {
if (temp_index + i == len - 1) return true;
if (nums[temp_index + i] >= (len - (temp_index + i))) return true;
if (nums[temp_index + i] != 0) s.push(temp_index + i);
}
}
return false;
}
};
用chatGPT分析超时的原因:
您的代码的时间复杂度为 O(2^n),其中 n 是数组的长度,因为在每个位置都可以有两个选择:跳或不跳,总共有 2^n 种可能的路径。这样的时间复杂度是无法通过本题的。
此外,您使用了栈来存储待搜索的位置,但这样的做法并不高效。因为每个位置最多只需要被遍历一次,而使用栈会重复遍历一些位置,导致时间复杂度进一步增加。
- 使用贪心算法
使用贪心算法,从左到右遍历数组,用一个变量来维护能够到达的最远距离,如果当前位置在这个最远距离之内,那么更新最远距离。如果遍历结束后最远距离大于等于数组的最后一个位置,那么就说明可以到达最后一个位置,否则就无法到达。
class Solution {
public:
bool canJump(vector<int>& nums) {
int n = nums.size();
int maxPos = 0; // 当前能到达的最远距离
for (int i = 0; i < n; i++) {
if (i > maxPos) return false; // 如果当前位置无法到达,则返回false
maxPos = max(maxPos, i + nums[i]); // 更新能够到达的最远距离
if (maxPos >= n - 1) return true; // 如果能够到达最后一个位置,返回true
}
return false;
}
};