算法就是一個解決問題時的一個計算過程python
在算法的角度上理解程序:程序 = 數據結構 + 算法算法
數據結構:數據的儲存(好比定義的列表...等等的變量)數據結構
算法:就是一個動態操做變量的過程函數
——因此其實函數也屬於算法,固然函數的定義只能解決一些很是簡單的問題spa
——順而言之,其實算法的表現形式,也是以函數的形式在表現的3d
時間複雜度的引入blog
問題1很好回答,固然是第一組代碼的運行時間最短,可是用什麼方式來體現呢?遞歸
還須要引入一個生活中的實例,內存
經過這個實例,很直觀的能表述出什麼呢?class
很明顯,咱們都知道,幾毫秒<幾秒<幾分鐘<幾小時<幾天/幾星期/幾個月<幾年
因此咱們能夠類比此實例,用一個能分清大小的式子來評估算法的運行效率:
O(1)< O(logn)<O(n)<O(nlogn)<O(n²)<O(n²logn)<O(n³)
而這個式子表達的是什麼意思呢?以下說明:
好比剛剛最初的print代碼:
其中O表示的就是大概的一個,同生活案例中的幾,而括號中的內容則表示了此程序的規模
而什麼又算做一個規模呢?下例:
類比以前所講內容,咱們能夠很直觀的獲得如上圖的結果,可是!這個結果是錯誤的!
經過這樣的答案咱們也不難看出規模指的其實就是相同量級的程序,圖中3所代指的規模
並無上升到等同於n的規模,而n的規模也並無上升到n²的規模,因此用一個大概值來表示
其中O的涵義也反映了這個時間複雜度的斷定標準,即一個大概的值
而logn有又什麼涵義呢?下面仍然用一組實例說明:
可見,當算法過程出現折半的時候,複雜度的式子中會出現logn。
綜上所說:如何簡單快速的判斷算法的複雜度
1.肯定問題規模——>n
2.循環減半過程——>logn
3.k層關於n的循環——>n^k
這三點適用於絕大多數簡單的狀況,複雜狀況則須要根據算法執行過程判斷
其表達方式與時間複雜度徹底同樣,
對於空間換時間的理解:
——代碼寧願佔用更多的內存,也要讓它能實現的更快【硬件的問題都是小問題(不是對於我)】
遞歸有兩個特色:一是調用自身,二是結束條件
因此根據這兩個條件咱們先行對下面幾個函數進行一下判斷:
有上圖可知,func3和func4爲遞歸正確調用的方法,可是打印輸出的內容確不相同,咱們用圖來表示一下其運行過程,
首先是func3
執行過程如圖,外層大框表示函數的調用,裏面小框爲print過程,而後反覆如此,因此呢,咱們看到的打印結果,以x=4
爲例:順序爲,4,3,2,1
而func4,運行以下圖:
執行過程如圖,外層大框表示函數的調用,裏面小框爲print過程,而後反覆如此,這些與func3運行一直,惟一不一樣的就是打印
代碼的位置不一樣,因此呢根據 如箭頭的運行程序打印的結果是:1,2,3
上面兩個函數的方法其實就是遞歸描述的一種思惟方式,那麼遞歸思想又是從何 而來的呢?
實際上是根據這樣一則故事而來,也被稱之爲漢諾塔問題,咱們以3個圓盤爲例解析一下此問題,
那麼若是是N個圓盤呢?其實咱們能夠根據上圖總結出必定的規律,其實整個過程主要就分爲了三步,
將第N個盤子看作一部分,前N-1個盤子看作一部分,整個過程其實就是,默認三根木棍分別由A、B、C表示
首先將前N-1個盤子,由A通過C移動到B,
而後將第N個盤子,由A移動到C,
最後在前前N-1個盤子,由B通過A移動到C,這樣就完成了整個過程,這也引入了咱們python算法中的漢諾塔算法:
def hanoi(n,a,b,c):
# n表示n個盤子
# a,b,c則表示了三根木棍
if n>0:
hanoi(n-1,a,c,b) # 將前n-1由a通過c移動到b
print('moving from %s to %s'%(a,c)) # 將n由a移動到c
hanoi(n-1,b,a,c) # 將前n-1有b通過a移動到c
hanoi(3,"A","B","C")
由此咱們獲得了漢諾塔移動次數的遞推式,
也就是兩個n-1次的移動,加上1次移動,n-1次是前n-1個圓盤的,1次是最大圓盤的