漫畫算法-小灰的算法之旅node
魏夢舒(@程序員小灰)著程序員
小灰用漫畫(可愛的手繪小倉鼠)的形式,給算法這顆「炮彈」包上了「糖衣」,讓算法的爲力潛藏於內,外表再也不嚇人,變得萌萌噠,Q彈可愛。面試
本書經過主人公小灰,用漫畫的形式講述了算法與數據結構的基礎知識、複雜多變的算法面試及算法的實際應用。算法
「學習算法,咱們不須要死記硬背那些冗長複雜的背景知識、底層原理、指令語法......須要作的是領悟算法思想、理解算法對內存空間和性能的影響,以及開動腦筋去尋求解決問題的最佳方案。相比編程領域的其餘技術,算法更純粹,更接近數學,也更具備趣味性。」 -- 做者說編程
算法數組
algorithm。始於計算出1+2+3+4...+10000的結果。首先把從1到10000這10000個數字兩兩分組相加,以下:數據結構
1 + 10000 = 10001
2 + 9999 = 10001
3 + 9998 = 10001
......函數
一共有多少組這樣結果相同的和呢?有10000/2即5000組,即結果:(1 + 10000) * 10000 / 2 = 50005000
。性能
在數學上稱這種等差數列求和的方法爲:高斯算法。學習
在數學領域:算法是用於解決一類問題的公式和思想。
在計算機領域:算法本質是一序列程序指令,用於解決特定的運算和邏輯問題。衡量算法好壞的重要標準有兩個:
應用:運算、查找、排序、尋找最優路線、面試等。
數據結構
數據結構是算法的基石。若是把算法比喻成美麗靈動的舞者,那麼數據結構就是舞者腳下廣闊而堅實的舞臺。
data structure,是數據的組織、管理和存儲格式,其使用的目的是爲了高效地訪問和修改數據。
數據結構組成方式:
時間複雜度
是對一個算法運行時間長短的量度,用大O表示,記做T(n) = O(f(n))
直白地講,時間複雜度就是把程序的相對執行時間函數T(n)簡化爲一個數量級,這個數量級能夠是n、n²、n³等。
推導出時間複雜度,有以下幾個原則:
好比:
執行次數是T(n) = 3n,最高階項爲3n,省去係數3,轉化的時間複雜度爲T(n) = O(n)
執行次數是T(n) = 5logn,最高階項爲5logn,省去係數5,轉化的時間複雜度爲T(n) = O(logn)。5logn,數學中的對數。
執行次數是T(n) = 2,只有常數量級,轉化的時間複雜度爲T(n)=O(1)
執行次數是T(n) = 0.5n² + 0.5n,最高階項爲0.5n²,省去係數0.5,轉化的時間複雜度爲T(n) = O(n²)
誰更節省時間呢?結論以下:
O(1) < O(logn) < O(n) < O(n²)
空間複雜度
space complexity。是對一個算法在運行過程當中臨時佔用存儲空間大小的度量,用大O表示,記做S(n) = O(f(n))
數組
有限個,在內存中順序存儲。
內存是由一個個連續的內存單元組成的,每個內存單元都有本身的地址。
數組中的每個元素,都存儲在小小的內存單元中,而且元素直接緊密排列,既不能打亂元素的存儲順序,也不能跳過某個存儲單元進行存儲。
操做:
插入、刪除的時間複雜度都是O(n)
優點:很是高效的訪問能力,只要給出下標,就能找到對應元素。
劣勢:插入、刪除效率低下。數組元素連續緊密地存儲在內存中,插入、刪除元素都會致使大量元素被迫移動,影響效率。
數組適合讀操做多、寫操做少的場景。鏈表和數組正好相反。
鏈表
一種在物理上非連續、非順序的數據結構,由若干節點(node)所組成。
單向鏈表的每個節點包含兩部分,存放數據的變量data,指向下一個節點的指針next。
鏈表的第一個節點被稱爲頭結點,最後一個節點被稱爲尾節點。尾結點的下一個節點指向空。
雙向鏈表,每個節點除了擁有 data 和 next,還擁有指向前置節點的 prev 指針。
數組在內存中的存儲方式是順序存儲,鏈表 在內存中的存儲順序是隨機存儲。
數組在內存中佔用了連續完整的存儲空間,而鏈表採用了見縫插針的方式,鏈表的沒一個節點分佈在內存的不一樣位置,依靠next指針關聯起來。這樣能夠靈活有效地利用零散的碎片空間。
鏈表操做:
;鏈表的插入和刪除的時間複雜度:若是不考慮插入、刪除操做以前查找元素的過程,只考慮純粹的插入、刪除操做,時間複雜度爲O(1)
數組 vs 鏈表:數組可以利用下標快速定位元素,對於讀操做多、寫操做少的場景很是使用。而鏈表的有事在於能靈活的進行插入和刪除操做,適用於讀操做少、寫操做多的場景。
棧和隊列
數據存儲的物理結構和邏輯結構:
棧:stack。一種線性數據結構,棧中的元素只能先進後出(FILO,First In Last Out)。最先進入的元素存放的位置叫做棧底,最後進入的元素存放的位置叫做棧頂。用數組、鏈表都可以實現。
棧的基本操做:
入棧、出棧的時間複雜度:O(1),由於只會影響到最後一個元素。
隊列:queue。一種線性數據結構,隊列中的元素只能先進先出(FIFO,First In First Out)。隊列的出口端叫做隊頭(front),隊列的入口端叫做隊尾(rear)。用數組、鏈表都可以實現。
隊列的基本操做:
額外:循環隊列、雙端隊列、優先隊列。
散列表
散列表:也稱哈希表,hash table。是存儲 key-value 映射的集合,時間複雜度接近於O(1)。本質上也是一個數組。
哈希函數:經過某種方式,把 key 和數組下標進行轉換的函數。
散列表的讀寫操做:
樹
tree,是n個節點的有限集。有以下特色:
樹的最大層級樹,被稱爲樹的高度或深度。
相關節點
二叉樹
樹的一種特殊形式。樹的每一個節點最多有2個孩子節點。
二叉樹的兩個孩子節點,一個被稱爲左孩子,一個被稱爲右節點。
二叉樹有兩種特殊形式:滿二叉樹、徹底二叉樹。
滿二叉樹:一個二叉樹的全部非葉子節點都存在左右孩子,而且全部葉子節點都在同一層接上。簡言之,滿二叉樹的每個分支都是滿的。
徹底二叉樹:對一個有n個節點的二叉樹,按層級順序編號,則全部節點的編號爲從1到n。若是這個樹全部節點和一樣深度的滿二叉樹的編號爲從1到n的節點位置相同,則這個二叉樹爲滿二叉樹。
一棵樹,若爲滿二叉樹,那麼必定是徹底二叉樹。反之,不必定。
在內存中存儲:
二叉樹的應用:查找操做、維持相對順序。
二叉樹的遍歷:
從節點之間位置關係的角度:
從更宏觀的角度:
二叉堆:本質上是一種徹底二叉樹。
二叉堆的根節點,叫做堆頂。最大堆的堆頂是整個堆中最大元素,最小堆的堆頂是整個堆中最小元素。
優先隊列:基於二叉堆實現:
觀後感:回想起了不少大學學習時的場景與概念(專業:軟件工程)