劍指offer系列-簡單總結


思維導圖來自 數據結構與算法看這一篇就夠了
在這裏插入圖片描述

1. 數據結構

1.1 鏈表

鏈表相關問題常常伴隨着指針的使用。
面試題18 刪除鏈表的節點

雙指針

面試題24 反轉鏈表

間隔k步的雙指針

面試題22 鏈表中倒數第k個節點

倍速雙指針

面試題23 鏈表中環的入口節點

消除鏈表長度差

面試題52 兩個鏈表的第一個公共節點

建造僞節點

例如新建1個值爲無窮小的節點
node = Node(float(’-inf’))

1.2 數組

pass

1.3 字符串

滑動窗口法,什麼時候擴大窗口,什麼時候縮小窗口,什麼時候移動窗口。不是隻適用於字符串。
樸素匹配法
KMP法

1.4 數字

求商 //
求餘 %
右移1位 >> 1,相當於除以2
左移1位 1 <<,相當於乘以2
a & 1 判斷a的奇偶,結果爲1爲奇,爲0爲偶數
a ^ a 異或自己的結果爲0
a ^ 0 異或零的結果爲本身
轉換爲字符串,通過字符串解決問題

1.5 棧(LIFO)

充分考慮站的後進先出特點

1.6 隊列(FIFO)

充分考慮隊列的先進先出特點。

1.7 哈希表

哈希表是一個用空間換時間的典型,因爲哈希表的讀取只需要O(1),所以在很多時候都是可以用哈希表來降低時間複雜度的。

需要注意的是,在python3.6中字典是有序的(按照插入順序),具體的請查看這篇博客 爲什麼Python 3.6以後字典有序並且效率更高?

1.8 樹

樹相關的算法一般用遞歸、隊列或棧。
樹的問題使用遞歸時最好理解的,能使用遞歸的話,優先使用遞歸。

深度優先遍歷(DFS)

深度優先遍歷常常與棧相關。

廣度優先遍歷(BFS,或者叫層序遍歷)

廣度優先遍歷常常與隊列相關。

1.9 圖

Dijkstra’s 算法

1.10 排序

詳情見 圖解十大經典排序算法

在這裏插入圖片描述

冒泡排序

最簡單的一種排序算法。先從數組中找到最大值(或最小值)並放到數組最左端(或最右端),然後在剩下的數字中找到次大值(或次小值),以此類推,直到數組有序排列。算法的時間複雜度爲O(n^2)。與選擇排序不同的是,在每次遍歷中,冒泡排序常常要交換多次,也就是一步步往上冒。

選擇排序

從數組中找到最大值或者最小值並放到數組的最左端或最右端,每遍歷1次才進行1次交換。

插入排序

插入排序的基本思想就是將無序序列插入到有序序列中。通常將數組的第一個元素看做有序數組,然後將後邊的元素不斷地插入到前面這個有序數組中。

快速排序

每次找一個基準值,左邊的元素都比基準值小,右邊的值都比基準值大。

一趟快速排序的具體做法爲:設置兩個指針low和high分別指向待排序列的開始和結尾,記錄下基準值baseval(待排序列的第一個記錄),然後先從high所指的位置向前搜索直到找到一個小於baseval的記錄並互相交換,接着從low所指向的位置向後搜索直到找到一個大於baseval的記錄並互相交換,重複這兩個步驟直到low=high爲止。

希爾排序

希爾排序(Shell’s Sort)也是一種插入排序,它是簡單插入排序經過改進之後的一個更高效的版本,也稱爲縮小增量排序。希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便終止。

歸併排序

歸併字面上的意思是合併,歸併算法的核心思想是分治法,就是將一個數組一刀切兩半,遞歸切,直到切成單個元素,然後重新組裝合併,單個元素合併成小數組,兩個小數組合併成大數組,直到最終合併完成,排序完畢。

桶排序

桶排序是將待排序集合中處於同一個值域的元素存入同一個桶中,也就是根據元素值特性將集合拆分爲多個區域,則拆分後形成的多個桶,從值域上看是處於有序狀態的。對每個桶中元素進行排序,則所有桶中元素構成的集合是已排序的。

堆排序

堆排序可以說是一種利用了堆的概念來排序的選擇排序。分爲兩種方法:

大頂堆:每個節點的值都大於或等於其子節點的值,在堆排序算法中用於升序排列。

小頂堆:每個節點的值都小於或等於其子節點的值,在堆排序算法中用於降序排列。

2. 常用算法

雙指針法、對撞雙指針法

對撞雙指針就是,某些情況下左指針右移,某些情況下右指針左移,當兩指針碰撞時退出循環。

三指針法

面試題49. 醜數

摩爾投票法

面試題39 數組中出現次數超過一半的數字

二分法

常常要求序列有序,當然也有變種。

遞歸、記憶化遞歸

常用於二叉樹的相關問題,由於遞歸可能會存在重複計算問題,所以有了記憶化遞歸(將之前計算的結果保存起來,供直接使用,避免重複計算)

窮舉法

這個沒啥好說的,就是暴力法。

動態規劃(dynamic programming,簡稱dp)

動態規劃最關鍵的就是找到狀態轉移方程,也可以說成是遞推公式,根據前面的某些狀態推導出當前的狀態。

貪心法

貪心算法是指在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,只做出在某種意義上的局部最優解。貪心算法不是對所有問題都能得到整體最優解,關鍵是貪心策略的選擇,選擇的貪心策略必須具備無後效性,即某個狀態以前的過程不會影響以後的狀態,只與當前狀態有關。
解題的一般步驟是:
1.建立數學模型來描述問題;
2.把求解的問題分成若干個子問題;
3.對每一子問題求解,得到子問題的局部最優解;
4.把子問題的局部最優解合成原來問題的一個解。

分治法

分治法的設計思想是:將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。

分治策略是:對於一個規模爲n的問題,若該問題可以容易地解決(比如說規模n較小)則直接解決,否則將其分解爲k個規模較小的子問題,這些子問題互相獨立且與原問題形式相同,遞歸地解這些子問題,然後將各子問題的解合併得到原問題的解。這種算法設計策略叫做分治法。

回溯法

在包含問題的所有解的解空間樹中,按照深度優先搜索的策略,從根結點出發深度探索解空間樹。當探索到某一結點時,要先判斷該結點是否包含問題的解,如果包含,就從該結點出發繼續探索下去,如果該結點不包含問題的解,則逐層向其祖先結點回溯。(其實回溯法就是對隱式圖的深度優先搜索算法)。

若用回溯法求問題的所有解時,要回溯到根,且根結點的所有可行的子樹都要已被搜索遍才結束。

而若使用回溯法求任一個解時,只要搜索到問題的一個解就可以結束。

分支限界法

回溯算法是深度優先,那麼分支限界法就是廣度優先的一個經典的例子。回溯法一般來說是遍歷整個解空間,獲取問題的所有解,而分支限界法則是獲取一個解(一般來說要獲取最優解)。

總結

我覺得,遇到一個算法題,一定要能對這個題目進行分類,就像高中時候做數學題一樣,拿到這個題之後,要了解它的考點是什麼,我應該用什麼方法來解決,掌握了這一點就是把握住了大方向,就算最後還是做不出來也不會差的太遠。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章