Leetcode題解系列——45. Jump Game II(c++版)
阿新 • • 發佈:2018-12-18
題目大意:與之前的跳躍遊戲一樣,從下標0出發,檢視是否能跳躍到陣列的最後一個下標。陣列的每個元素都是能跳躍的距離,現在要求輸出跳躍到最後下標的最小步數。
注意點:
- 這次要求所給的陣列都能到達最後下標,即無需考慮到達不了的情況
- 不一定每次都走最大的距離,才能最快到達最後下標,故要改變之前的貪心策略
- 注意判斷陣列只有一個元素的情況
一.演算法設計
這次要在第一個跳躍遊戲的基礎下,新增一個count陣列,儲存每個結點到達下標所用的最小跳躍次數,但是要記得將第一個下標的跳躍次數設定為0,即不需要跳躍即可到達。
每個結點找出所能到達的最遠距離,如果這個最遠距離小於n-1即最後下標,那麼將count陣列對應下標的元素賦值,該值為count[i]+1即到達該i結點的次數+1和它本身的次數的最小值
當最遠距離大於最大下標,也亦然,只不過不是賦值最遠距離下標而是賦值n-1.
最後count[n-1]所儲存的一定是到達該下標的最少次數,這可以通過將問題分解成許多子問題來思考,因為子問題也是找到達前一個點的最少步數,所以最少步數的和也一定是到達終點的最少步數。
二.演算法實現
class Solution {
public:
int jump(vector<int>& nums) {
int n = nums.size();
if(n == 1) return 0;
int max_num = 0;
int count[30000]={0}; //要讓count[0] = 0
for(int j = 1; j < 30000; j++){
count[j] = 300000;
}
for(int i = 0; i < n; i++){
max_num = max(max_num, i+nums[i]);
if(max_num <= n-1) count[max_num] = min(count[i]+ 1, count[max_num]);
else count[n-1] = min(count[i]+1,count[n-1]);
}
return count[n-1];
}
};
三.演算法改進
當然也可以不用維持這一個count陣列,只需要每一次所要跳躍的選擇都選擇能跳躍最遠的結點。怎麼為能跳躍最遠呢,不僅要當前的下標大,還與陣列元素相關 next_max=max(next_max,nums[i]+i);
這樣選擇多次,直到判斷最遠距離大於最遠下標,即可輸出選擇的次數。
class Solution {
public:
int jump(vector<int>& nums) {
if(nums.size()<2){
return 0;
}
int level=0,current_max=0,next_max=0,i=0;
while(i<nums.size()){
level++;
for(;i<=current_max;i++){
next_max=max(next_max,nums[i]+i);
if(next_max>=nums.size()-1) return level;
}
current_max=next_max;
}
return level;
}
};