1. 程式人生 > >Leetcode題解系列——45. Jump Game II(c++版)

Leetcode題解系列——45. Jump Game II(c++版)

題目大意:與之前的跳躍遊戲一樣,從下標0出發,檢視是否能跳躍到陣列的最後一個下標。陣列的每個元素都是能跳躍的距離,現在要求輸出跳躍到最後下標的最小步數。

注意點:

  1. 這次要求所給的陣列都能到達最後下標,即無需考慮到達不了的情況
  2. 不一定每次都走最大的距離,才能最快到達最後下標,故要改變之前的貪心策略
  3. 注意判斷陣列只有一個元素的情況

一.演算法設計

這次要在第一個跳躍遊戲的基礎下,新增一個count陣列,儲存每個結點到達下標所用的最小跳躍次數,但是要記得將第一個下標的跳躍次數設定為0,即不需要跳躍即可到達。

每個結點找出所能到達的最遠距離,如果這個最遠距離小於n-1即最後下標,那麼將count陣列對應下標的元素賦值,該值為count[i]+1即到達該i結點的次數+1和它本身的次數的最小值

count[max_num] = min(count[i]+1, count[max_num]);

當最遠距離大於最大下標,也亦然,只不過不是賦值最遠距離下標而是賦值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;
    }
};