简单暴力到dp的优化(萌新篇)
想寫一系列文章,總結一些題目,看看解決問題、優化方法的過程到底是什么樣子的。
?
系列問題一:斐波那契數列問題
在數學上,斐波納契數列以如下被以遞歸的方法定義:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)根據定義,前十項為1, 1, 2, 3, 5, 8, 13, 21, 34, 55
問題一:
給定一個正整數n,求出斐波那契數列第n項(這時n較小)
解法一:最笨,效率最低,暴力遞歸,完全是抄定義。請看代碼
def f0(n):if n==1 or n==2:return 1return f(n-1)+f(n-2)?
分析一下,為什么說遞歸效率很低呢?咱們來試著運行一下就知道了:
?
比如想求f(10),計算機里怎么運行的?
?
每次要計算的函數量都是指數型增長,時間復雜度O(2^(N/2))<=T(N)<=O(2^N),效率很低。效率低的原因是,進行了大量重復計算,比如圖中的f(8),f(7).....等等,你會發現f(8)其實早就算過了,但是你后來又要算一遍。
如果我們把計算的結果全都保存下來,按照一定的順序推出n項,就可以提升效率, 斐波那契(所有的一維)的順序已經很明顯了,就是依次往下求。。
優化1
def f1(n):if n==1 or n==2:return 1l=[0]*nl[0],l[1]=1,1for i in range(2,n):l[i]=l[i-1]+l[i-2]return l[-1]?
時間復雜度o(n),依次往下打表就行,空間o(n).
繼續優化:既然只求第n項,而斐波那契又嚴格依賴前兩項,那我們何必記錄那么多值呢?記錄前兩項就行了
?
優化2
def f2(n):a,b=1,1for i in range(n-1):a,b=b,a+breturn a此次優化做到了時間o(n),空間o(1)
附:這道題掌握到這里就可以了,但是其實有時間o(log2n)的方法
?
優化三:
學習過線性代數的同學們能夠理解:
?
結合快速冪算法,我們可以在o(log2n)內求出某個對象的n次冪。(在其它專題詳細講解)
注意:只有遞歸式不變,才可以用矩陣+快速冪的方法。
注:優化三可能只有在面試上或競賽中用,當然,快速冪還是要掌握的。
?
經過這個最簡單的斐波那契,大家有沒有一點感覺了?
好,我們繼續往下走
(補充:pat、藍橋杯原題,讓求到一萬多位,結果模一個數。
可以每個結果都對這個數取模,否則爆內存,另:對于有多組輸入并且所求結果類似的題,可以先求出所有結果存起來,然后直接接受每一個元素,在表中查找相應答案)
?
問題二:
一只青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法。
依舊是找遞推關系,分析:跳一階,就一種方法,跳兩階,它可以一次跳兩個,也可以一個一個跳,所以有兩種,三個及三個以上,假設為n階,青蛙可以是跳一階來到這里,或者跳兩階來到這里,只有這兩種方法。它跳一階來到這里,說明它上一次跳到n-1階,同理,它也可以從n-2跳過來,f(n)為跳到n的方法數,所以,f(n)=f(n-1)+f(n-2)
和上題的優化二類似。
因為遞推式沒變過,所以可以用優化三
?
問題三:
我們可以用2*1的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?提示,大矩形看做是長度吧
請讀者自己先思考一下吧。。。仔細看題。。仔細思考
如果n是1,只有一種,豎著放唄;n是2,兩種:
,
n等于3,三種:
?
題意應該理解了吧?
讀到這里,你們應該能很快想到,依舊是斐波那契式遞歸啊。
對于n>=3:怎么能覆蓋到三?只有兩種辦法,從n-1的地方豎著放了一塊,或者從n-2的位置橫著放了兩塊唄。
和問題二的代碼都不用變。
?
問題四:
給定一個由0-9組成的字符串,1可以轉化成A,2可以轉化成B。依此類推。。25可以轉化成Y,26可以轉化成z,給一個字符串,返回能轉化的字母串的有幾種?
比如:123,可以轉化成
1 2 3變成ABC,
12 3變成LC,
1 23變成AW,三種,返回三,
99999,就一種:iiiii,返回一。
分析:求i位置及之前字符能轉化多少種。
兩種轉化方法,一,字符i自己轉換成自己對應的字母,二,和前面那個數組成兩位數,然后轉換成對應的字母
假設遍歷到i位置,判斷i-1位置和i位置組成的兩位數是否大于26,大于就沒有第二種方法,f(i)=f(i-1),想反,等于f(i-1)+f(i-2)
注意:遞歸式不確定,不能用矩陣快速冪
?
(這幾個題放到這里就是為了鍛煉找遞歸關系的能力,不要只會那個爛大街的斐波那契)
?
''' 斐波那契問題: 斐波納契數列以如下被以遞歸的方法定義: F(1)=1 F(2)=1 F(n)=F(n-1)+F(n-2)(n>=2,n∈N*) ''' #暴力抄定義,過多重復計算 def f0(n):if n==1 or n==2:return 1return f(n-1)+f(n-2) #記錄結果后依次遞推的優化,時間O(N) def f1(n):if n==1 or n==2:return 1l=[0]*nl[0],l[1]=1,1for i in range(2,n):l[i]=l[i-1]+l[i-2]return l[-1] #既然嚴格依賴前兩項,不必記錄每一個結果,優化空間到O(1) def f2(n):a,b=1,1for i in range(n-1):a,b=b,a+breturn a?
總結
以上是生活随笔為你收集整理的简单暴力到dp的优化(萌新篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode226 反转二叉树
- 下一篇: leetcode147 对链表进行插入排