原题
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
示例 1:
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。示例 2:
输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jump-game
解法
一开始好像没什么思路。
先来模拟下这个游戏:
[2, 3, 1, 1, 4]
我们在 2,nums[0] 处最多可以跳两个,跳最远距离( 2 )来到 1, nums[2],接着跳最远的距离( 1 )来到 1,nums[3] ,最后到达最后一个位置 4,nums[4]。
再来个例子试试:
[3, 3, 1, 0, 4]
我们按照我们第一次模拟的方法,直接跳到 0,nums[4] ,直接完蛋。
但是,我们第一次可以 不跳 最远距离( 3 ) ,只跳一步不就可以到 3,nums[1] ,然后又可以到达最后一个位置了吗?
思路不就来了吗?
我们遍历每个位置,如果前一个位置的能跳到的最远距离大于当前位置,说明我们可以跳到当前位置,我们为了防止出现第二个例子的情况,我们把当前位置能跳到的最远距离和前一个位置能跳到的最远距离比较,如果大,说明我们可以跳到更远的地方。如果能跳到的最远距离大于最后一个位置的距离,返回结果。
class Solution {
public:
bool canJump(vector<int> &nums) {
int size = nums.size();
int maxDistance = 0;
/* i表示当前位置,nums[i] + i 表示可以跳到的最远的位置 */
for (int i = 0; i < size; ++i) {
if (i <= maxDistance) {
maxDistance = max(nums[i] + i, maxDistance);
}
}
return maxDistance >= size - 1;
}
};
总结
感觉贪心就是人的一种本能,所以做贪心题目时,或许可以联系下生活。
这题也折腾挺久的,一开始把每个位置所能到达的最远的距离用向量保存起来,然后遍历该向量,如果下一个位置能跳到的最远距离大于上一个位置的,就更新最远位置。仔细想想,这样做很明显不对。
这题感觉应该还可以加大难度,求最少步数。
看了下相似题目,果然有个Ⅱ。
附跳跃游戏Ⅱ代码:
class Solution {
public:
int jump(vector<int> &nums) {
int size = nums.size();
if (size == 1) {
return 0;
}
int maxDistance = 0; // 能跳的最远距离
int cnt = 0; // 步数
int board = 0; // 能跳的最远距离的位置
for (int i = 0; i < size - 1; ++i) {
maxDistance = max(nums[i] + i, maxDistance);
if (i == board) {
board = maxDistance;
++cnt;
if (board >= size - 1) {
return cnt;
}
}
}
return cnt;
}
};
诗情画意
青玉案·元夕 辛弃疾 东风夜放花千树,更吹落,星如雨。宝马雕车香满路。凤箫声动,玉壶光转,一夜鱼龙舞。 蛾儿雪柳黄金缕,笑语盈盈暗香去。众里寻他千百度,蓦然回首,那人却在,灯火阑珊处。