LeetCode 55. Jump Game && 45. Jump Game II
阿新 • • 發佈:2018-12-13
題解
LeetCode 上這種題目的變形非常多。因為比較相似這次兩題一起寫,思路比較連貫一點。
第一題 55. mid 難度。這題只要判斷能否到達尾部。我們用一個變數 cur_max記錄可到達的最遠位置,遍歷陣列即可。 注意此處出現的span陣列,意為在i處時能到達的最遠位置,這是此題的關鍵。
第二題 45. hard。 也不難,算最小步長,但是測試用例裡有一個case卡時間。 最小最大,很明顯是dp的感覺。 那麼我們設 dp[ i ] 為到達 i 位置是所需的最小步長。 我想到了兩種狀態轉移方法。
- dp[ i ] = min { dp[ k ] + 1 | k : span[ k ]>=i } // 後退式
- 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];
}