1. 程式人生 > 其它 >力扣 leetcode 45. 跳躍遊戲 II

力扣 leetcode 45. 跳躍遊戲 II

問題描述

給你一個非負整數陣列 nums ,你最初位於陣列的第一個位置。

陣列中的每個元素代表你在該位置可以跳躍的最大長度。

你的目標是使用最少的跳躍次數到達陣列的最後一個位置。

假設你總是可以到達陣列的最後一個位置。

提示:

  • 1 <= nums.length <= 10^4
  • 0 <= nums[i] <= 1000

示例

示例 1:

輸入: nums = [2,3,1,1,4]
輸出: 2
解釋: 跳到最後一個位置的最小跳躍數是 2。
     從下標為 0 跳到下標為 1 的位置,跳 1 步,然後跳 3 步到達陣列的最後一個位置。

示例 2:

輸入: nums = [2,3,0,1,4]
輸出: 2

解題思路

這裡我們可以從起始位置出發,根據當前可跳躍次數,來更新後面位置的最少跳躍次數。如果後面某個位置 j 是由當前位置 i 跳躍過去的,即當前位置最少需要跳躍 x 次,則判斷 x+1 是否小於 i 的最小跳躍次數,如果小於,則更新它的值。

但是這樣做存在大量重複遍歷的節點,例如 nums=[5,1,1,1,1,1,1] ,在這裡,我們從 0 開始跳躍兩步即可抵達終點,按我們之前的方法卻要遍歷多 1, 2, 3, 4 這四個位置。因此,我們可以記錄一下上一輪最遠的跳躍位置,如果當前位置跳躍無法跳出上一輪的最遠位置,就不需要再考慮這個位置了(因為跳躍次數一定比上一次的跳躍次數多)。

同時,在這種情況下,我們發現,每次更新最少跳躍次數,更新值都不超過上一次的更新值。這對我們有兩個幫助:1,只要我們從某個點出發,最遠跳躍位置達到了末尾,則可以終止判斷了,已經找出了最少跳躍次數;2,每次更新最少跳躍次數時,我們無需與上一次儲存的值進行比較。

最終的程式碼如下:

class Solution {
public:
    int jump(vector<int>& nums) {
        vector<int> dp(nums.size(), 0x7ffffff);
        int tmp;
        int pre_max = 0;
        int max = 0;
        int max_idx = nums.size() - 1;
        dp[0] = 0;
        for(int i = 0; i < nums.size(); i++){
            if(i + nums[i] < max){
                continue;
            }
            else{
                pre_max = max;
                max = (i + nums[i]) < nums.size() ? (i + nums[i]) : (max_idx) ;
            }
            if(pre_max == max_idx){
                break;
            }
            tmp = dp[i] + 1;
            for(int j = pre_max + 1; j <= max; j++){
                dp[j] = tmp;
            }
        }
        return dp[max_idx];
    }
};