1. 程式人生 > >LeetCode 55. Jump Game && 45. Jump Game II

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

題解

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]; }