[LeetCode P45] Jump Game II

原题:

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.

For example:
Given array A = [2,3,1,1,4]

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.

解法:
这一段不是很重要,只是我自己的思路
我先讲讲我自己的思路,我的想法是,从最后一个index,找到离末尾最远但是可以一步到达的坐标i,然后我们再让i成为最后一个index,继续向前找。开始我用O(n^2)的想法去实现它,时间超限,后来我想,可以记录所有的坐标和它们可达的最远位置,然后按照最远位置进行升序排序,最后从后向前,找到可以达到末尾的最小的坐标就可以了,那么sort的复杂度是O(nlogn),实际上我们用桶排序也可以做到O(n),但不是个靠谱的办法。
O(nlogn)的复杂度已经AC了,但我觉得肯定有更简单的O(n)算法,discuss里给了我答案。
下面是我从discuss里整理的算法,看到这篇博客的朋友可以直接看这里
可以主要理解一下注释。

class Solution {
public:
    int jump(vector<int>& nums) {
        // 理解了题目的意思以后,我们可以在O(n)/O(1)的复杂度下完成
        // 主要的想法是我们要记录跳k次,最远可以跳到哪里
        // 我们可以这样想,第一次跳跃,是我们0=0thMax,下一次我们要在什么时候跳跃呢?
        // 应该是当i=1thMax的时候,因为不跳,我就到不了更远的地方,而最远,我们可以跳到curMax
        // 因为curMax记录了0~i范围内我们可以到达的最远距离
        // 成功AC
        /* -------------分割线-------------*/
        // 另外一种思路我觉得也不错,就是把k次跳跃的查找看成BFS
        // 我们对这k层进行搜索,并且维护了一个k-1层的末端值,当我们遍历到末端的时候
        // 说明第k层已经完全找到,才可以继续向k+1层进发
        int kthMax = 0, k = 0, curMax = 0;
        for (int i = 0; kthMax < nums.size() - 1; ++i)
        {
            curMax = max(curMax, nums[i] + i);
            // 这里我们不用考虑最后一个,因为首先题意确定了我们一定有解
            // 所以在count-2处需要jump的时候,说明这次jump一定可以到count-1
            if (i == kthMax)
            {
                kthMax = curMax;
                k++;
            }
        }
        return k;
    }
};

下面也给出我自己AC的代码,不是很好的解决思路,虽然理论上也可以做到O(n),但对于排序,我们一般还是以O(nlogn)的复杂度来看到。

// struct mypair
// {
//     int i, end;
// };

class Solution {
public:
    int jump(vector<int>& nums) {
        if(nums.size() == 1) return 0;
        vector<mypair> farest;
        int jump = 0;
        for (int i = 0; i < nums.size(); ++i)
        {
            mypair p;
            p.i = i;
            p.end = i + nums[i];
            farest.push_back(p);
        }
        sort(farest.begin(), farest.end(), [](mypair p1, mypair p2)->bool{
            return p1.end < p2.end || (p1.end == p2.end && p1.i < p2.i);
        });
        int target = nums.size() - 1;
        int i = farest.size() - 1;
        int minIndex = farest.size();
        while(i >= 0)
        {
            while(farest[i].end >= target){
                if(farest[i].i == 0) return jump+1;
                minIndex = min(minIndex, farest[i].i);
                i--;
            }
            jump++;
            target = minIndex;
        }
        return jump;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值