45. 跳跃游戏 II
class Solution {
public:
int jump(vector<int>& nums) {
int Jumps = 0;
int PrevRightmost = 0;
int Rightmost = 0;
// The problem ensures that we can always jump to the last one, so there's
// no need to check the last element anymore.
for (int i = 0; i < nums.size() - 1; ++i) {
Rightmost = std::max(Rightmost, i + nums[i]);
if (i == PrevRightmost) {
// We've collected all possible Jumps inside [0, PrevRightmost]. It's
// time that we choose the Rightmost one and jump!
PrevRightmost = Rightmost;
++Jumps;
}
}
return Jumps;
}
};
评论区里的这个解释非常好,尤其是代码注释当中的这句:
总体策略:在当前索引位置下,跳跃一步能到达的所有位置的边界内,选择那个下次能跳的更远的那个位置
这样你就能理解为什么我们直到 i == PrevRightmost 的时候才往后跳,并且更新 Jumps 了——因为我们已经考察完了在 PrevRightmost 之前的所有可能的最大跳跃距离,并通过 max() 记录在了 Rightmost 当中。
不考虑 i == nums.size() - 1 是为了防止类似于
的这种情况。这种情况下你会发现你在 i = 0 时跳过第一次之后,PrevRightmost 刚好等于 1 == nums.size() - 1。但是当下个循环 i = 1 时,我们其实已经到达了终点,然而 i == PrevRightmost 的判断会导致我们不必要地自增了一个 Jumps。
二刷
class Solution {
public:
int jump(vector<int>& nums) {
int Result = 0;
int Rightmost = 0;
int End = 0;
for (int i = 0; i < nums.size() - 1; ++i) {
Rightmost = max(i + nums[i], Rightmost);
if (i == End) {
++Result;
End = Rightmost;
}
}
return Result;
}
};
背吧背吧,至少55. 跳跃游戏三刷真写出来了,这个乍一想想不到也无所谓了。