算法:算法
- 一個有限指令集
- 接受一些輸入(有些狀況下不須要收入)
- 產生輸出
- 必定在有限步驟以後終止
- 每一條指令必須:
- 有充分明確的目標,不能夠有歧義
- 計算機能處理的範圍以內
- 描述應不依賴於任何一種計算機語言以及具體的實現手段
其實說白了,算法就是一個計算過程解決問題的方法。咱們如今已經知道數據結構表示數據是怎麼存儲的,而「程序=數據結構+算法」,數據結構是靜態的,算法是動態的,它們加起來就是程序。bash
對算法來講有輸入,有輸出,至關於函數有參數有返回值。咱們寫算法的時候習慣把算法封裝到一個函數中。數據結構
好,從上面咱們知道了什麼是算法,下面我再說什麼是好的算法?
在解決同一個問題的時候,咱們一般會有不少種不同的算法,區別就在於,有的算法比較笨,有的算法比較聰明,那咱們怎麼去衡量它們誰好誰壞呢?咱們一般有下面兩個指標:函數
- 空間複雜度:根據算法寫成的程序在執行時佔用存儲單元的長度。
- 時間複雜度:根據算法寫成的程序在執行時耗費時間的長度。
先舉個例子說,若是讓你打印十個整數,你那個程序可能瞬間就給出結果了,若是讓你打印十萬個整數呢?這你就得多等一會了。因此這個程序運行的時間,就跟你要處理的數據是十個仍是十萬個是相關的,這個十或十萬就是咱們要處理的數據的規模。咱們把它叫作n,是一個變量的話,那咱們這個程序所用的時間和空間都跟這個n是有直接關係的。解決一個問題有不少中不一樣的方法,你在設計這個方法的時候,必定要把這兩個要素考慮清楚。一不當心,若是空間複雜度太大的話,你那個程序就可能直接爆掉了,非正常中斷,我一會會在後面講,時間複雜度若是太大的話,你就可能等很長時間都等不出結果。ui
先來看上面圖片中的幾組代碼,我是用Python表示的,你在看的時候考慮兩個問題:spa
- 四組代碼中,哪組的運行時間最短?
- 用什麼方式來體現算法運行的快慢?
剛纔說n能夠看做數據的規模,規模不同,運行時間確定也不同,並且所用時間也很差肯定,不一樣的n會獲得不一樣的時間,因此咱們用時間複雜度來表示算法運行的快慢。
先來看下面圖片中的幾個生活中的事件,估計時間:設計
這裏你會發現咱們會用「幾」表示一個大概,後面還有相應的時間單位,那時間複雜度也參照相似的方法:
時間複雜度:用來評估算法運行效率的一個式子
看上面圖片所示,先說print(‘Hello World’),它的時間複雜度表示爲O(1),O嚴格來講,它表示數學上一個式子的上界,咱們能夠簡單的理解爲就是一個估計,大約,至關於上面說的「幾」。1能夠理解爲是個運行單位(相似於秒這樣的單位),爲何是O(1),由於print(‘Hello World’)只執行了一次,同理分析第二個:code
for i in range(n):
print('Hello World')
它的時間複雜度表示爲O(n),由於這組代碼執行了n次。n仍是個單位,同理,分析第三個:blog
for i in range(n):
for j in range(n):
print('Hello World')
它的時間複雜度表示爲O(),由於是有兩層循環,因此是,仍是個單位。第四個你本身就能夠分析了,我就很少此一舉了。但千萬不要覺得就是這麼簡單,咱再看下面代碼圖片:
排序
看到這個圖片,你是否是感受很良好,和你猜的差很少是吧,哈哈,不要高興的太早,告訴大家,錯了,它們的時間複雜度不是這樣的。
爲何?我說了,「1」是單位,但「3」不是單位,3是3乘1,就好比說在生活中,問你一壺水燒多長時間,沒有人回答說是三個幾分鐘或者幾個三分鐘。再說第二個,是單位,n也是個單位,可是比n大,因此咱們在估計時用大單位,就比如生活中問你大概睡了多久,你通常說是幾個小時,而不是說幾個小時零幾分鐘,你強調的是一個大概的時間,明白了吧。
因此正確的時間複雜度是這樣的:
第一個爲何是O(1),首先print('Hello World')打印一次和打印三次實際的影響不大吧,就是無論執行幾回,只要它的規模不上升到n這麼大的時候,換句話說,1是個單位,因此無論怎樣,由於這是表示近似,不是表示精確的,因此是O(1).好,再看下面這個圖片:
當你的循環減半的時候,時間複雜度就會變爲O(logn)。因此你能夠這樣記,當算法過程出現循環折半的時候,複雜度式子中會出現logn。
- 時間複雜度是用來估計算法運行時間的一個式子(單位)
- 通常來講,時間複雜度高的算法比時間複雜度低的算法慢
在空間複雜度中須要注意的一點就是理解「空間換時間」,在研究一個算法的時候,時間比空間重要。