前言
记录一下刷题历程 力扣第55题 跳跃游戏
跳跃游戏
原题目:给你一个非负整数数组 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 , 所以永远不可能到达最后一个下标。
分析
我们使用贪心算法,target为索引。我们从倒数第二个位置开始遍历,位置3最大可以跳1步,可以跳到最后一个索引,此时把目标索引target更新为3,当前只要能从0跳到位置3就说明可以从位置0跳到最后一个位置即索引4。我们继续往前遍历,遍历到索引2,从位置2最多可以跳1步,因为从2到3可达,那么我们继续更新索引为2。然后继续遍历到位置1,从1最多可以跳3步,可以直接跳到最后一个索引,而且从位置1到位置2也是可达的,我们继续更新索引为1。我们继续向前遍历到位置0,位置0最多可以跳两步,说明0到1也是可达的,更新索引target为0。当我们逆序遍历完数组target为0时,就说明从0到最后一个位置是可达的。可以根据下面的图来理解:
代码如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
int target = nums.size() - 1; // 初始化目标位置为数组最后一个位置
// 从倒数第二个位置向前遍历数组
for (int i = nums.size() - 2; i >= 0; i--) {
// 如果当前位置 i 可以跳跃至目标位置 target 或更远
if (i + nums[i] >= target) {
target = i; // 更新目标位置为当前位置 i
}
}
// 如果最终目标位置为数组起始位置 0,则说明可以到达最后一个位置,返回 true
// 否则返回 false
return target == 0;
}
};
解释注释
1.目标位置初始化:
int target = nums.size() - 1;
target 初始化为数组 nums 的最后一个位置,表示起始时希望能够直接跳到数组的最后一个位置。
2.倒序遍历数组:
for (int i = nums.size() - 2; i >= 0; i–) {
从数组倒数第二个位置开始向前遍历,因为最后一个位置不需要再判断。
3.更新目标位置:
if (i + nums[i] >= target) {
target = i;
}
如果当前位置 i 能够跳跃至目标位置 target 或更远(即 i + nums[i] >= target),则更新 target 为当前位置 i。
这里的逻辑是通过贪心算法,每次尽可能更新可以到达的最远位置。
4.判断是否可以到达:
return target == 0;
最终判断 target 是否等于数组的起始位置 0。如果等于,则表示可以从起始位置开始到达最后一个位置,返回 true。
否则,返回 false,表示无法从起始位置开始到达最后一个位置。
时间复杂度
时间复杂度: O(n),其中 n 是数组 nums 的长度。只需要单次遍历数组,因此时间复杂度是线性的。