力扣 leetcode 45. 跳躍遊戲 II
阿新 • • 發佈:2022-11-29
問題描述
給你一個非負整數陣列 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]; } };