题目地址:Jump Game II
题目简介:
给定一个非负整数数组,最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度,目标是使用最少的跳跃次数到达数组的最后一个位置。
示例:
输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
说明:假设你总是可以到达数组的最后一个位置。
题目解析:
1、超时的动态规划:
结合上题,纪录到达第i个位置的最小跳数,根据上一跳的位置和跳数更新,算法时间复杂度O()
class Solution {
public:
int jump(vector<int>& nums) {
int len = nums.size();
if (len <= 1)
return 0;
int dp[len];
memset(dp, 127, sizeof(dp));
dp[0] = 0;
for (int i = 0; i < len - 1; i++)
{
int temp = nums[i];
for (int j = 1; j <= temp; j++)
{
if (i + j < len)
dp[i + j] = min(dp[i + j], dp[i] + 1);
else if(i + j == len - 1)
return dp[len - 1];
else
break;
}
}
return dp[len - 1];
}
};
2、贪婪算法(参考地址)
在每个位置上,扫描范围内最大的数字,确定可以到达的最大的边界。当扫描位置达到了最大的边界时,说明需要继续向下走一步,更新当前所能达到的最大边界,直到扫描完所有的数据。例如:
- 初始位置上的数字为2,他能达到的范围是橙色的。又3 + 1 > 2 + 2,选择位置为3的数字,跳到4。
- 但是只按照上述的方法去找,很可能会遇到只有0可以跳的位置。所以需要对每一个节点都需要考虑,例如上图。
- 结合动态规划的思想,当扫描位置达到了上一次更新的边界时,说明需要达到当前位置的最小跳数已经确定。那么只需继续向下考虑,找到下一个所能达到的最大边界,并确定在当前边界内最小的跳数。
总的来说,就是先确定一个范围,在这个范围内,所有点的点都可以达到,然后在这个范围内的点去找最远的距离的点。
C++版:
class Solution {
public:
int jump(vector<int>& nums) {
int end = 0, maxPosition = 0, steps = 0;
for(int i = 0; i < nums.size() - 1; i++)
{
maxPosition = max(maxPosition, nums[i] + i);
if(i == end)
{
end = maxPosition;
steps++;
}
}
return steps;
}
};
static auto _=[](){ios::sync_with_stdio(false);return 0;}();
关于代码的最后一句的加速原理:解析 static auto x = []() { std::ios::sync_with_stdio(false);std::cin.tie(nullptr);return 0;}()