LeetCode #45. Jump Game II 数组 贪心
Description
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
Example:
Input: [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2.
Jump 1 step from index 0 to 1, then 3 steps to the last index.
Note:
- You can assume that you can always reach the last index.
思路
解法一
注意,题目中保证了从每个序列的头部起跳后最终一定能跳到尾部,根据这个信息能少掉很多条件判断。
本来想用 #55 中解法一的贪心解题,但发现局部最优(当前可跳跃的最远距离)可能不是全局最优,所以不能照搬原来的贪心。
// 贪心陷入局部最优的例子,在三个 2 间连跳两下
[2, 2, 2, 1, 5, 3]
受上面这个“陷入局部最优”的例子启发,我们将原本每个位置贪心一次,改成“范围贪心”,即在当前可跳跃的最远距离里寻找下一次跳跃时跳最远的点。比如上面的例子里,起始点索引为 0,可跳跃的最远点索引是 2,那么就在索引为 1 到 2 这两点里寻找这次要跳的位置,且该位置能保证下一次跳跃的距离最远。比较后发现,索引为 1 点最远能跳到 3,索引为 2 的点最远能跳到 4,所以这次跳到第三个 2 的位置。之后在以第三个 2 为起始点,进行下一次贪心。
时间复杂度:O(n) = 保存每个点能跳到的最远距离 O(n) + 范围贪心 O(n)
空间复杂度:O(n) = 保存每个点能跳到的最远距离 O(n)
耗时 8 ms, faster than 94.34%, Memory 8.3 MB
class Solution {
public:
int jump(const vector<int> &nums) {
if (nums.size() < 2) return 0;
int end = nums.size() - 1;
// longest distance that can reach from each position
vector<int> dist(nums.size());
for (int i = 0; i < end; ++i) {
// update longest distance jump from i
dist[i] = i + nums[i];
}
int steps = 0; // min numbers of jump from the beginning to the end
int cur = 0;
int reach = dist[cur];
while (reach < end) {
int max_jump = INT_MIN;
for (int i = cur + 1; i <= reach; ++i) {
if (max_jump < dist[i]) {
max_jump = dist[i];
cur = i;
}
}
reach = max_jump;
++steps;
}
++steps;
return steps;
}
};
参考
————全心全意投入,拒绝画地为牢