恕我直言,這道題做的十分的爽,解法千變萬化,不知是哪位神人出的?
解法一:(雖然跑不出來,但是依然要貼上)
遞歸版,但數據量大時leetcode上run會失敗。
class Solution:
def uniquePaths(self, m: 'int', n: 'int') -> 'int':
if m==1 or n==1:
return 1
else:
return self.uniquePaths(m, n-1) + self.uniquePaths(m-1, n)
解法二:空間換時間(貌似也換不了多少時間)
採用一個M*N的二維數組,第一行和第一列均爲1,因爲到達其位置的路徑只有一種。那麼到達[i, j]位置的路徑有[i-1,j]+[i,j-1]種。
class Solution:
def uniquePaths(self, m: 'int', n: 'int') -> 'int':
num_L = []
for i in range(m):
num_L.append([])
for i in range(0, n):
num_L[0].append(1)
for i in range(1, m):
num_L[i].append(1)
for i in range(1, m):
for j in range(1, n):
num_L[i].append(num_L[i-1][j]+num_L[i][j-1])
return num_L[m-1][n-1]
解法三:
這種方法要細說。以題目中的例子爲例,讓我們仔細想一想,當格子的長寬爲3*7時,
我們要往下兩步,往右六步,往下或是往右互不干涉。這不就是八個數的全排列嗎?只不過這八個數裏相同的數很多而已,全排列請參考這個。
但沒想到的是,利用這種解法依然時間超出限制。本以爲這還是一種比較好的解法,但是依然行不通,看來帶有遞歸形式的解法可能不適於這題的求解。
解法四:
上面的一個解法沒有解決問題很是令我失望,按常理這裏題目肯定還會有更好的解法。回顧之前的解法二,空間上是否可以縮的更小呢?解法二中採用了二維數組的方法,主要是來存儲之前已經計算過的值。具體來講,便是用當前位置上面和左面的值來計算當前的值,實際上每次運算的過程只需要兩行的存儲空間,這樣的話便可以對解法二進行改進!
class Solution:
def uniquePaths(self, m: 'int', n: 'int') -> 'int':
if m > n:
self.uniquePaths(n, m)
cur = []
pre = []
for i in range(m):
cur.append(1)
pre.append(1)
for i in range(1, n):
for j in range(1, m):
cur[j] = cur[j-1]+pre[j]
pre, cur = cur, pre
return pre[m-1]
嗯!時間複雜度上終於算可以了,但是空間上依然消耗很大,肯定還有別的方法!
解法五:
繼續觀察上面的解法四,可以看到每次更新cur[i]位置的值時,需要用到cur[i-1]和pre[i],試問這時的pre是怎麼來的,對,沒錯,就是之前的cur。如果我們不更換cur和pre的話,當前cur[i]的值=cur[i](更換後的pre)+cur[i-1]。不說了,上代碼:
class Solution:
def uniquePaths(self, m: 'int', n: 'int') -> 'int':
if m > n:
self.uniquePaths(n, m)
cur = []
for i in range(m):
cur.append(1)
for i in range(1, n):
for j in range(1, m):
cur[j] += cur[j-1]
return cur[m-1]
但是很令人費解的是,即使是這樣,時間複雜度也只是beat了70%的人,不應該啊!
後來在某貼上看到公式大法:
class Solution:
# @return an integer
def uniquePaths(self, m, n):
aux = [[1 for x in range(n)] for x in range(m)]
for i in range(1, m):
for j in range(1, n):
aux[i][j] = aux[i][j-1]+aux[i-1][j]
return aux[-1][-1]
不得不說,還是公式好!