leetcode学习日记3-jump跳跃游戏2

leetcode学习日记3-jump跳跃游戏2

最近刷到一题,leetcode45 跳跃游戏II
第一遍做,肯定用dp。两重循环。
初始状态:数组dp表示这个位置要跳几次才能到达终点,每一个数开始都是MAX,最后一个位置是0;
循环:从后往前倒着找,两重循环。第一重索引每一个位置,第二重对这个位置和终点间的点循环查找所需要最少的跳跃次数。故时间复杂度是O(n2)。
转移方程:dp[i]=min(dp[i],dp[j]+1) (0<=i

感觉思路没什么问题……
然而数据惨不忍睹……
在这里插入图片描述
于是就看了一下大佬们的12ms答案,开始觉得难以置信,后来有点想明白了。
不用dp,这题居然贪心做。
贪心一遍扫描就可以得到答案。
所谓贪心,就是每次尽量跳到最远的那个点。
但是注意,下一次跳不能从这个点开始,而要从这个点和上一个点之间选择一个能够跳得最远的点,以它为起点找下一个点。
例如,这种情况
leetcode学习日记3-jump跳跃游戏2_第1张图片横线上方是nums[i],横线下方是i
模拟:两个指针,分别指向前一个位置p和下一个位置q;一个计数器ans

初始状态: p=0, q=0, ans=0

  1. p在0处,找可能到达的最大位置,即2,赋给q, ans++
  2. 找下一位置,在p, q中找一个点作为下一次起跳的起点 ,得到在这些点中最远能到的位置,把q赋给p,把这个位置赋给q
    此时p=2,q=max(nums[1]+2,nums[2]+3)=5, ans++;
  3. 再找下一位置,和上面一步方法相同,p=5, q=max(nums[3]+3,nums[4]+2,nums[5]+4)=9, ans++;
  4. 只需使得q越过终点,即不用找下一步跳跃的位置,结束循环
    注意,在找下一位置时,必须遍历所有可能的点(即p,q之间的所有点),而不能单纯地用最远点来算

这样看来,每个点只需要遍历一次,时间复杂度O(n)

class Solution {
public:
    int jump(vector<int>& nums) {
        int ans = 0, n = nums.size(), i = 0, q = 0;
        while (q < n - 1) {
            ++ans;
            int p = q;
            for (; i <= p; ++i) {
                q = max(q, i + nums[i]);
            }
            
        }
        return q;
    }
};

你可能感兴趣的:(leetcode学习日记3-jump跳跃游戏2)