「这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战」
55. 跳跃游戏
题目描述
给定一个非负整数数组 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步还是几步,只需要判断 调到的一格 是否能跳到最后一个数组元素位置,每次取最大的跳跃步数,判断是否有元素的跳跃范围达到最大的数组数目。
- 贪心算法:
- 局部最优:每次取最大的跳跃距离
- 全局最优:最后判断局部最优中是否有能满足条件的,满足则就是全局最优的结果
代码
class Solution
{
public:
bool canJump(vector<int> &nums)
{
int cover = 0;
if (nums.size() == 1)
{
return true;
}
for (int i = 0; i <= cover; i++)
{
// 记录每一步的最大跳跃范围
cover = max(i + nums[i], cover);
// 如果跳跃的范围能够满足数组的数目,则可以到达最后一个下标
if (cover >= nums.size() - 1)
{
return true;
}
}
}
};
复制代码
45. 跳跃游戏 II
题目描述
给你一个非负整数数组 nums
,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。
示例 1:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
复制代码
示例 2:
输入: nums = [2,3,0,1,4]
输出: 2
复制代码
解析
与上一题思路相似,判断每一步能够到达的最远下标。如果当前能到达最远下标,则停止;如果不能到达最远下标,就继续走一步,判断下一步能否到达最远下标。
- 当移动下标到达了当前覆盖的最远距离下标时:
- 1、如果当前覆盖的最远距离下标时终点,直接返回,不需再走一步
- 2、如果当前覆盖的最远距离下标不是终点,需要再走一步
代码
class Solution
{
public:
int jump(vector<int> &nums)
{
// 当前覆盖的最远下标
int curDistance = 0;
// 下一步覆盖的最远距离下标
int nextDistance = 0;
// 最大步数
int steps = 0;
for (int i = 0; i < nums.size(); i++)
{
// 更新下一步覆盖的最远下标
nextDistance = max(nextDistance, nums[i] + i);
// 遇到当前的最大覆盖下标
if (i == curDistance)
{
// 如果当前的最大覆盖下标还不是最后一个元素的下标
// 就需要再走一步
if (curDistance != nums.size() - 1)
{
steps++;
curDistance = nextDistance;
// 如果下一步的最大覆盖下标已经可以到达最后一个元素就停止
if (nextDistance >= nums.size() - 1)
{
break;
}
}
// 如果是终点就停止
else
{
break;
}
}
}
return steps;
}
};
复制代码
改进
不考虑移动后是否到达终点
class Solution
{
public:
int jump(vector<int> &nums)
{
// 当前覆盖的最远下标
int curDistance = 0;
// 最大步数
int steps = 0;
// 下一步覆盖的最远下标
int nextDistance = 0;
// 这里下标 i < nums.size()-1
for (int i = 0; i < nums.size() - 1; i++)
{
// 更新下一步的最远覆盖下标
nextDistance = max(nextDistance, nums[i] + i);
// 遇到当前覆盖的最远下标时
if (i == curDistance)
{
// 更新当前覆盖的最远下标
curDistance = nextDistance;
steps++;
}
}
return steps;
}
};
复制代码