leetcode 62.不同路徑
阿新 • • 發佈:2018-11-22
題目描述:
一個機器人位於一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。
機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。
問總共有多少條不同的路徑?
思路 :
從左上角到右下角總共需要走 m+n-2 步,其中 m-1 步向下,剩下的 n-1 步向右。所以這其實是一個簡單的排列組合問題...
答案應該是 C( m+n-2 , m-1 ),和與它對稱的 C( m+n-2 , n-1 )。挑一個簡單的計算就行。時間複雜度應該是O(min(m,n))
int uniquePaths(int m, int n) { int N=m+n-2; int M=m<n?m-1:n-1; //計算 C(N,M) //根據:C(N,i)=C(N,i-1)*(N-i+1)/i; //由於是先乘再除的,可能會出現中間結果超出int的情況,所以用long long ans=1; for(int i=1;i<=M;i++) ans=ans*(N-i+1)/i; return ans; }
測試執行0ms。
看了一下同樣是0ms的其他程式碼,感覺有點複雜。先去吃午飯再回來琢磨...
//邊吃午飯邊更新:
假定a[i][j]代表從左上角到 ( i, j ) 格子的路徑總數。考慮到能抵達格子( i , j )只有兩類方式:1,從它左邊走過來;2,從它上面走過來。總路徑數,應該是這兩類路徑數之和。所以 a[i,j] = a[i-1,j] + a[i,j-1]。
int uniquePaths(int m, int n) { //初始化一個矩陣 int a[m][n]{0}; //對於第一行上的格子,只有一條路徑:一路向右 for(int i=0;i<n;i++) a[0][i]=1; //第一列同理 for(int i=0;i<m;i++) a[i][0]=1; //其餘格子:a[i][j]=a[i-1][j]+a[i][j-1]; for(int i=1;i<m;i++) for(int j=1;j<n;j++) a[i][j]=a[i-1][j]+a[i][j-1]; return a[m-1][n-1]; }
注意我用了a[m][n],現在C++裡都可以這樣了?!
這個演算法的時間複雜度是O(m*n),空間複雜度也是O(m*n)。
另外注意到空間還有優化的餘地,改進演算法如下:
int uniquePaths(int m, int n) { //初始化一個矩陣 int a[n]{0}; //第一行 for(int i=0;i<n;i++) a[i]=1; //迭代求第i行的值 for(int i=1;i<m;i++) for(int j=1;j<n;j++) a[j]=a[j]+a[j-1]; return a[n-1]; }
時間複雜度不變,空間優化為O(n)。如果有必要,可以通過調換對行、列的迴圈順序,把空間優化為O(min(m,n))。