LeetCode 55. Jump Game && 45. Jump Game II

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/smmyy022/article/details/82949487

题解

LeetCode 上这种题目的变形非常多。因为比较相似这次两题一起写,思路比较连贯一点。

第一题 55. mid 难度。这题只要判断能否到达尾部。我们用一个变量
cur_max记录可到达的最远位置,遍历数组即可。
注意此处出现的span数组,意为在i处时能到达的最远位置,这是此题的关键。

第二题 45. hard。 也不难,算最小步长,但是测试用例里有一个case卡时间。
最小最大,很明显是dp的感觉。
那么我们设 dp[ i ] 为到达 i 位置是所需的最小步长。
我想到了两种状态转移方法。

  1. dp[ i ] = min { dp[ k ] + 1 | k : span[ k ]>=i } // 后退式
  2. dp[ i ] = min{ dp [ j ] + 1 | j : i<= j <=span[ i ] } //前进式

本质是一样的,但是循环方式不一样。
还要剪枝,方法就是第一次出现的span[]超过了n就可以结束dp循环了。


Code

bool canJump(vector<int>& nums) {
        int n =nums.size();
        vector<int> span(n);
        
        for(int i=0;i<n;i++) span[i]=i+nums[i];
        
        int cur_max=0;
        for(int i=0;i<n;i++){
            if(i<=cur_max && span[i]>cur_max)
                cur_max = span[i];
        }
        return cur_max>=n-1;        
    }
int jump(vector<int>& nums) {
        int n =nums.size();
        vector<int> dp(n,99999),span(n);
        if(n<2) return 0;
        
        for(int i=0;i<n;i++) span[i]=i+nums[i];
        
        dp[0]=0;
        /* 1. method valid but  time limit exceeded
        if(span[0]>=n-1) return dp[0]+1;
        for(int i=0;i<n;i++){
            for(int j=0;j<i;j++){
                if( span[j]>= i){
                    dp[i] = min(dp[i],dp[j]+1);
                    // prune 剪枝
                    if(span[i]>=n-1) return dp[i]+1;
                }
            }
        }
        */
        // 2. method valid
        for(int i=0;i<n;i++){
            for(int j=i;j<=span[i]&&j<n;j++){// j may exceed the range
                dp[j] = min(dp[i]+1,dp[j]);
                // prune 剪枝
                if(span[j]>=n-1) return dp[j]+1;
            }
        }
        return dp[n-1];
    }

猜你喜欢

转载自blog.csdn.net/smmyy022/article/details/82949487