【LeetCode】LeetCode之跳跃游戏Ⅱ——暴力解法+动态规划+贪婪算法
1.題目描述
🔐給你一個非負整數數組 nums ,你最初位于數組的第一個位置。
數組中的每個元素代表你在該位置可以跳躍的最大長度。
你的目標是使用最少的跳躍次數到達數組的最后一個位置。
假設你總是可以到達數組的最后一個位置。
?示例 1:
輸入: nums = [2,3,1,1,4]
輸出: 2
解釋: 跳到最后一個位置的最小跳躍數是 2。
從下標為 0 跳到下標為 1 的位置,跳 1 步,然后跳 3 步到達數組的最后一個位置。
?示例 2:
輸入: nums = [2,3,0,1,4]
輸出: 2
?提示:
1 <= nums.length <= 104
0 <= nums[i] <= 1000
2.暴力解題思路
💎反向查找,我們可以考慮最后一步前的位置,因此我們可以考慮最后一步跳躍前所在的位置,該位置通過跳躍能夠到達最后一個位置。你可能我會說如果有多個能夠達到最后一個位置,該怎么選擇呢?我們肯定會選擇距離最后一個位置最遠的那一個。
- 從下標0開始遍歷,當遍歷到下標為2的時候發現能夠達到最后一個位置,所以此時講end置為下標2
- 從下標0開始遍歷,發現下標0能到達end,結束
- 結果就為2
3.暴力解法代碼
public static int jump2(int[] nums) {int size = nums.length;if (size == 1) {return 0;}int minJumps = 0;for (int i = 0; i < size; i++) {if (size == 2) {minJumps++;break;}if (nums[i] + i >= size - 1) {minJumps++;size = i + 1;i = -1;}}return minJumps;}復雜度分析
時間復雜度:O(n^2)
空間復雜度:O(1)
提交到LeetCode會發現超出時間限制。
4.動態規劃思路
本題的核心是最少的跳躍次數,其實我們應該首先想到的是動態規劃,首先就是如何分解子問題?
📑求解f(n)無非就是求距離最后一個位置最遠且可達的位置+1。那么它的dp[i]就代表當前位置的最少跳躍次數。轉移方程那肯定就是dp[n]=dp[a]+1,a就代表距離n最遠的那個位置的下標。【由于這個a是無法直接確定的,所以需要一個內層循環提供支持】
5.動態規劃解題代碼
public static int jump(int[] nums) {int[] dp = new int[nums.length];dp[0] = 0;for (int i = 1; i < nums.length; i++) {for (int j = 0; j < i; j++) {if (nums[j] + j >= i) {dp[i] = dp[j] + 1;break;}}}return dp[nums.length - 1];}復雜度分析
時間復雜度:O(n^2)
空間復雜度:O(n)
不過慶幸的是提交到LeetCode能通過,但也很極限
我們可以發現本題使用動態規劃,有很多重復的比較,這種就接近遞歸了,無法做到很大的優化。那有沒有一種能達到時間復雜度為O(n)的方法呢?
6.貪婪算法解題思路
📅我們都知道貪心算法具有貪心選擇性,從一個狀態轉移到另一個狀態,不會對后續造成影響,往往具有唯一的最優選擇。所以本題我們可以長期維護一個最遠跳躍距離maxPos,遍歷數組,每遍歷一個元素就更改其最遠跳躍距離maxPos,當達到臨界值end時,將當前最遠跳躍maxPos賦值給臨界值end并將跳躍次數+1.
7.貪婪算法解題代碼
復雜度分析:
時間復雜度:O(n)
空間復雜度:O(1)
提交到LeetCode
總結
以上是生活随笔為你收集整理的【LeetCode】LeetCode之跳跃游戏Ⅱ——暴力解法+动态规划+贪婪算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【LeetCode】LeetCode之跳
- 下一篇: 【LeetCode】LeetCode之乘