Leetcode个人题解55

LEETCODE专题


55. Jump Game

题目要求:
这里写图片描述

这里题目给定了一个序列,从下标0开始,以该下标访问到的数字n为最大距离向前移动1至n个下标,问我们是否能够通过这种方式到达最后一个下标。


问题:

  1. 这里存在着一个问题,由于可访问的距离为1至n,我们如何确定下一次要停在哪一个下标?
  2. 如何确定通过这种方式不能够访问到最后一个下标?

思路:

  1. 这里,可以顺着题目给的步骤来做。从当前下标,访问距离最大且可到达的下一个下标;下一次从上一次到达的下标开始,再去访问距离最大且可到达的下一个下标……这样看起来好像没多大问题,但实际上有一个致命的缺陷——我们无法保证当前下标能够访问到的距离最大且可到达的下标以后可以访问到最远下标。举个例子:

    输入:[2, 3, 0,  3]
    下标访问序列:[0, 2],永远到达不了下标3。
    

    但是实际上,这个序列是可以到达下标3的,对应的下标访问序列:[0, 1, 3]。
    所以,这个思路实际上非常的naive,并不能够解决问题。

  2. 笔者尝试改进了这个思路,采用递归方式访问下标,每一次访问距离最大的下标后,还可以继续访问之前的下标,只要该下标大于当前下标。然后再设置一个与给定序列登场的全局序列以记录相应的下标是否访问过,若访问过则跳过。这个解法相当于DFS,是可以访问所有能够访问的下标的。当然了,这解法相当费时。所以,笔者submit一次之后,很自然的,超时了。
  3. 最后采用的是记录当前下标和下一个最远下标的方法。在当前下标cur和当前下标能够访问到的最远下标next之间选择落脚点,包括目前的最远下标,比较并获得这些落脚点能够到达的最远下标m2并将该下标设置为下一次移动的最远下标。在下一次移动时,当前下标cur为上一次的最远下标next,当前最远下标为上一次移动的m2。假如能够到达,那么最后会出现next >=最后的下标的情况。如果不能够到达,那么最后肯定是next == cur的情况,因为只有无法移动才不能够到达最后下标。

class Solution {
public:

    bool canJump(vector<int>& nums) {
        /*
         * Start jumping from index 0.
         * Each time set 'cur' to be the standing index,
         * set 'next' to be the next standing index,
         * get the farthest standing index by scanning all index(es) between 'cur' and 'next'.
         * To understand it, we can set m1 to be the scanner from 'cur' + 1 to 'next' - 1,
         * compare every m1 + nums[m1] and next + nums[next], get the maximum of the current pass,
         * which is then the 'next' of the next pass.
         * And the 'cur' of the next pass is the 'next' now.
         * 
        */
        int cur = 0;
        int next = nums[cur];
        int m1, m2;
        while (next < nums.size() - 1) {
            if (cur == next) return false;
            m1 = cur;
            m2 = next + nums[next];
            while (++m1 < next) {
                m2 = m1 + nums[m1] > m2 ? m1 + nums[m1] : m2;
            }
            cur = next;
            next = m2;
        }

        return true;
    }
};

时间复杂度:O(n)

猜你喜欢

转载自blog.csdn.net/m0_37576233/article/details/78747324