LeetCode题解
生活随笔
收集整理的這篇文章主要介紹了
LeetCode题解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目是這樣的: 一個機器人位于一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。 機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。 問總共有多少條不同的路徑?
輸出: 3
解釋:
從左上角開始,總共有 3 條路徑可以到達右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右 輸入: m = 7, n = 3
輸出: 28 這道題其實跟那個踩階梯的題很相似:“假如有10步臺階,一次可走一步或兩步,那么要走到達臺階頂,有幾種走法,我們都知道,這個是斐波那契問題,遞歸就可以了”。 我們可以這么解,假設最后一格是a[m][n],那么能到達a[m][n]的只有a[m-1][n]和a[m][n-1]。同理,要到達a[m-1][n],也只能從a[m-1-1][n]和a[m-1][n-1]; 要到達a[m][n-1],也只能從a[m-1][n-1]和a[m][n-1-1],這是個遞歸問題。直到a[i][j]中i=1或者j=1,當i=1時,就只可以能時從a[i][j-1]到達,當j=1時,同樣,也只能從a[i-1][j]到達; 于是,遞歸的邊界找到了。 可能上面說的不直觀,請看下面:
``` r(m,3)的值?????? r(m,4)的值?? r(m,4)-r(m-1,4)的差值
r(1,3)=1???????? r(1,4)=1???????? 3 r(2,3)=3???????? r(2,4)=4???????? 6? r(3,3)=6???????? r(3,4)=10?????? 10 r(4,3)=10??????? r(4,4)=20?????? 15?? r(5,3)=15??????? r(5,4)=35?????? 21?? r(6,3)=21??????? r(6,4)=56?????? 28?? r(7,3)=28??????? r(7,4)=84?????? 36?? r(8,3)=36??????? r(8,4)=120????? 45?? r(9,3)=45??????? r(9,4)=165
有沒有發現 r(9,4)=r(8,4)+45=r(8,4)+r(9,3)=r(7,4)+r(8,3)+r(8,3)+r(9,2) r(8,4)=r(7,4)+36=r(7,4)+r(8,3)=r(6,4)+r(7,3)+r(7,3)+r(8,2) . . . . . ``` 于是我們很快想到了遞歸函數怎么寫: ``` public int uniquePaths2(int m, int n) { if (m == 1) { return 1; } if (n == 1) { return 1; } return uniquePaths2(m - 1, n) + uniquePaths2(m, n - 1); } ```
運行一下:
結果對了,現在把參數值變大一點:
時間還湊合,再變大,這次運行時間有點久了:
超過了兩分鐘! 為什么呢,請看上面的發現那里:在我們計算r(9,4)的時候是不是中間會計算兩次r(8,3),并且r(8,4)和r(9,4)中間都會有r(7,4)的計算,而這些重復計算是很浪費時間的。對這塊不了解的可以看這篇文章:https://mp.weixin.qq.com/s/llvtdxaPc29CNkcmtPHxKw 于是,為了避免重復計算,這個函數需要改寫,我們可以這樣,在計算r(8,3)的時候把r(8,3)的值保存起來,這樣下次計算r(8,3)的值的時候可以直接獲取,不需要再計算了,根據這個思路,把算法改良一下: ``` public int uniquePaths3(int m, int n) { int[][] all = new int[m][n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i == 0 || j == 0) { all[i][j] = 1; } else { all[i][j] = all[i - 1][j] + all[i][j - 1]; } } } return all[m - 1][n - 1]; } ```
再看看運行結果:
快了好多是不是!
例如:
輸入: m = 3, n = 2輸出: 3
解釋:
從左上角開始,總共有 3 條路徑可以到達右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右 輸入: m = 7, n = 3
輸出: 28 這道題其實跟那個踩階梯的題很相似:“假如有10步臺階,一次可走一步或兩步,那么要走到達臺階頂,有幾種走法,我們都知道,這個是斐波那契問題,遞歸就可以了”。 我們可以這么解,假設最后一格是a[m][n],那么能到達a[m][n]的只有a[m-1][n]和a[m][n-1]。同理,要到達a[m-1][n],也只能從a[m-1-1][n]和a[m-1][n-1]; 要到達a[m][n-1],也只能從a[m-1][n-1]和a[m][n-1-1],這是個遞歸問題。直到a[i][j]中i=1或者j=1,當i=1時,就只可以能時從a[i][j-1]到達,當j=1時,同樣,也只能從a[i-1][j]到達; 于是,遞歸的邊界找到了。 可能上面說的不直觀,請看下面:
``` r(m,3)的值?????? r(m,4)的值?? r(m,4)-r(m-1,4)的差值
r(1,3)=1???????? r(1,4)=1???????? 3 r(2,3)=3???????? r(2,4)=4???????? 6? r(3,3)=6???????? r(3,4)=10?????? 10 r(4,3)=10??????? r(4,4)=20?????? 15?? r(5,3)=15??????? r(5,4)=35?????? 21?? r(6,3)=21??????? r(6,4)=56?????? 28?? r(7,3)=28??????? r(7,4)=84?????? 36?? r(8,3)=36??????? r(8,4)=120????? 45?? r(9,3)=45??????? r(9,4)=165
有沒有發現 r(9,4)=r(8,4)+45=r(8,4)+r(9,3)=r(7,4)+r(8,3)+r(8,3)+r(9,2) r(8,4)=r(7,4)+36=r(7,4)+r(8,3)=r(6,4)+r(7,3)+r(7,3)+r(8,2) . . . . . ``` 于是我們很快想到了遞歸函數怎么寫: ``` public int uniquePaths2(int m, int n) { if (m == 1) { return 1; } if (n == 1) { return 1; } return uniquePaths2(m - 1, n) + uniquePaths2(m, n - 1); } ```
運行一下:
?
結果對了,現在把參數值變大一點:
?
時間還湊合,再變大,這次運行時間有點久了:
?
超過了兩分鐘! 為什么呢,請看上面的發現那里:在我們計算r(9,4)的時候是不是中間會計算兩次r(8,3),并且r(8,4)和r(9,4)中間都會有r(7,4)的計算,而這些重復計算是很浪費時間的。對這塊不了解的可以看這篇文章:https://mp.weixin.qq.com/s/llvtdxaPc29CNkcmtPHxKw 于是,為了避免重復計算,這個函數需要改寫,我們可以這樣,在計算r(8,3)的時候把r(8,3)的值保存起來,這樣下次計算r(8,3)的值的時候可以直接獲取,不需要再計算了,根據這個思路,把算法改良一下: ``` public int uniquePaths3(int m, int n) { int[][] all = new int[m][n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i == 0 || j == 0) { all[i][j] = 1; } else { all[i][j] = all[i - 1][j] + all[i][j - 1]; } } } return all[m - 1][n - 1]; } ```
再看看運行結果:
?
快了好多是不是!
轉載于:https://www.cnblogs.com/aibaofeng/p/11098525.html
總結
以上是生活随笔為你收集整理的LeetCode题解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10 字符串相关操作
- 下一篇: HDU - 6183 Color it