跳躍遊戲,合計三道題。
55. Jump Game
1. 題目
2. 思路
這道題即考慮是否達到最後的一個位置,我們可以通過到達每一個下標處時,維護一個可達最大下標值
,判斷我們能否到達數組的最後一個下標。
3. 代碼
public boolean canJump(int[] nums) {
int maxIndex = 0;
for (int i = 0; i < nums.length; i++) {
// 可達最大下標值大於當前遍歷的下標值,則說明該下標無法被到達
if (maxIndex < i) {
return false;
}
// 更新可達最大下標值
maxIndex = Math.max(maxIndex, i + nums[i]);
// 可達最大下標值不小於數組最大下標值,則說明可以到達最後一個位置
if (maxIndex >= nums.length - 1) {
return true;
}
}
return false;
}
4. 運行結果
45. Jump Game II
1. 題目
2. 方法一
2.1 思路
該題目與上一道題的區別在於這個是求最少幾次可以到達,一個比較笨的方法是,我們可以維護一個數組來記錄到達每一個下標的最少次數,從頭往後遍歷每一個下標,更新從該下標能到達的位置的最少次數,最終來算出數組最後一個位置最少幾次可以到達。該思路需要一個額外的數組,空間複雜度爲o(n),而時間上,需要從頭到尾遍歷一次,同時每個節點又需要更新其能到達的下標位置的值,因此時間複雜度爲O(n²)
2.2 代碼
public int jump(int[] nums) {
int[] dp = new int[nums.length];
for (int i = 1; i < nums.length; i++) {
dp[i] = Integer.MAX_VALUE;
}
for (int i = 0; i < nums.length; i++) {
for (int j = 1; j <= nums[i] && i + j < nums.length; j++) {
dp[i + j] = Math.min(dp[i + j], dp[i] + 1);
}
}
return dp[nums.length - 1];
}
2.3 運行結果
3. 方法二
3.1 思路
上面的方法一思路簡單,但是時間複雜度比較高,我們考慮其他做法。
我們可以聯想Jump Game的第一題,第一題是問我們能否到達最後一個下標,即我們其實也是求了我們能到達最大下標處,那我們是不是也可以將這道題這麼考慮:我們需要求出最少幾步才能到達數組的末尾,即我們可以通過求第n步最遠能到達哪裏來進行判斷,即思路變爲求每增加一步時,我們可以到達的下標位置是多少
,是否已經到達了數組的末尾。這種思路只需要遍歷一次數組,空間複雜度爲O(n)。
3.2 代碼
public int jump1(int[] nums) {
// 跳躍的步數
int steps = 0;
// 當前步數可到達的最大下標
int maxIndex = 0;
// 增加一步可以到達的最大下標
int nextIndex = nums[0];
for (int i = 0; i < nums.length; i++) {
// 當前遍歷的下標值已經超過了當前步數可達的最大下標
if (i > maxIndex) {
steps++;
if (nextIndex >= nums.length - 1) {
break;
} else {
maxIndex = nextIndex;
}
}
// 更新下一步能到達最大下標
nextIndex = Math.max(nextIndex, i + nums[i]);
}
return steps;
}
3.3 運行結果
可以看到所需時間遠遠小於方法一。
1306. Jump Game III
1. 題目
2. 思路
這道題比較有意思,判斷的是從數組的某個下標開始,能否最終到達元素值爲0的下標處。這種題目,很容易聯想到遞歸的思路。
3. 代碼
private HashSet<Integer> set = new HashSet<>();
public boolean canReach(int[] arr, int index) {
// set中已有該下標,則說明出現循環,退出
if (index < 0 || index > arr.length - 1 || set.contains(index)) {
return false;
}
set.add(index);
// 判斷該點是否爲下標值爲0的地方,或者index + arr[index]跟index - arr[index] 是否爲下標值爲0的地方
if (arr[index] == 0 || canReach(arr, index + arr[index]) || canReach(arr, index - arr[index])) {
return true;
}
set.remove(index);
return false;
}
4. 運行結果
相關鏈接
本題代碼的github鏈接 —— 55. Jump Game
本題代碼的github鏈接 —— 45. Jump Game II
本題代碼的github鏈接 —— 1306. Jump Game III
其他 LeetCode 題目
LeetCode Top 100 Liked Questions 題目