【LeetCode】55. Jump Game

Problem Link

概要

给定一个非负整数的数组,从起始位置开始跳跃,每个数字代表能够跳跃的最大距离,判断是否能够跳跃到末尾位置。

贪心算法

回顾贪心算法的两个要素:

  • 在当前状态能够找到一个安全的行动;
  • 问题具有最优子结构。

很容易看出,本题具有最优子结构。每次将跳跃到的位置之前的元素删除,即可得到与原问题性质一致、但规模较小的子问题——在剩下的较小的数组中判断是否能从起始位置跳到末尾位置。因此尝试使用贪心算法解决本问题。

现在应当考虑如何进行安全的一步操作,以制定贪心策略,进一步来说,问题可以理解成视解为下标的一个序列,能否跳跃到一个在这个序列当中的一个位置。

错误的贪心策略可能有:

  • 从起始位置出发,每次跳跃到最远的位置。
  • 从起始位置出发,每次跳跃到数字最大的位置。
  • 从起始位置出发,每次跳跃到能够到达的位置的值之和最大的位置。

要注意的是,数组的起始位置不一定在解当中,因此从起始位置起步是不合适的,从末尾位置开始才是正解。

正确的贪心策略是:

从末尾位置出发向前找,每次找一个能够跳到末尾位置的位置,并从这个新位置出发重复寻找操作,直到回到了起始位置(成功)或无法再往前跳跃(失败)。

这样确保了每次都能找到一个在解中的位置,并且当多个位置满足要求时,由于它们都能到达同一个位置,这些位置也是相互能回溯到的。

如此这般,本题能够在遍历一遍数组($O(n)$)的情况下返回结果。

附录

本人解答