算法分析與設計複習算法
算法分析與設計複習
2016年初,研一上學期期末考試前,複習並總結算法分析與設計科目的內容。複習過程參照《算法導論》中文第2版,同時參照PPT,章節劃分根據PPT內容數組
概要:函數
第一章 概述優化
第二章 插入排序&分治策略編碼
第三章 複雜度分析設計
第四章 堆與堆排序3d
第五章 快速排序blog
第六章 線性時間排序排序
第七章 中位數和順序統計遞歸
第八章 動態規劃(DP)
第九章 貪心算法
第十章 最短路徑算法
第十一章 回溯法&分支限界法
第十二章 NP問題與一些概念
第一章 概述
-
算法的應用範圍
算法在諸如生物等諸多領域有其應用
-
算法的意義
算法在不少狀況下讓不可能完成的事情變成了可能,讓處理的很慢的過程變快。
-
一個鋪墊
一串不全爲負的數,怎麼取能拿到一段和最大的子串(最大子段和)
第二章 插入排序&分治策略
-
插入排序
- 掌握插入排序的方法
-
循環不變式的證實
初始化:
保持:
終止:
-
逐步計算插入排序的時間複雜度:
結論(基於RAM模型下):
Best Case:O(n)
Worst Case:O(n^2)
-
分治策略
-
MERGE Sort
- 掌握歸併排序的方法
-
分析歸併排序
- 經過遞歸式分析
- Best case:nlgn
- Worst case:nlgn
-
課後習題總結
- 推演一個插入排序的過程
- 循環不變式證實線性查找的正確性
- 對給定的時間複雜度表達式寫出Θ
- 推演一個MERGE Sort
- 算法設計題:能夠看*
第三章 複雜度分析
-
時間複雜度分析
-
歸併排序分析
-
代換法(證實手段)
- 作一個好的猜想
- 假設這個界對某一個範圍內成立
- 帶入得出結論
- 數學概括法證實結論正確
-
遞歸樹
- 時間複雜度的表達式是每一層拆分開銷之和加上最底層每個未知的開銷。
-
主定理(必會)
- 形如:T(n)=aT(n/b)+f(n)
-
三種狀況:
- 若存在ε>0,有f(n)=O(n^(log b(a)-ε)),則T(n)=Θ(n^(log b(a)))
- 若f(n)=Θ(n^(log b(a))),T(n)=Θ(n^(log b(a))lg(n))
- 若對某ε>0,有f(n)=Ω(n^(log b(a)+ ε)),且對常數c<1與全部足夠大的n,有af(n/b)<=cf(n),則T(n)=Θ(f(n))
-
必會技能
-
課後習題總結
-
代換法證實時間複雜度
- 猜想漸進確界,證實之
- 主方法可用狀況的練習
- 判斷主方法是否可用,肯定漸進上界
第四章 堆與堆排序
-
堆的概念
- 利用樹的數組存儲方式,PARENT(i) = i/2, LEFT(i) = 2i, RIGHT(i) = 2i + 1
-
兩個關鍵的函數
- MAX-HEAPIFY 已有堆的狀況下,加入新結點後調整堆以使得其知足堆的條件。O(lgn)
- BUILD-MAX-HEAP 基於無序數組調整爲大頂堆Θ(n)
- 其中,BUILD-MAX-HEAP是由(n/2)向下取整次MAX-HEAPIFY組成的,但其時間複雜度是Θ(n)
-
堆排序時間複雜度
- 時間複雜度由兩部分組成,1次BUILD-MAX-HEAP,n-1次MAX-HEAPIFY,故結果爲T(n)=Θ(n)+nO(lg n)=O(nlgn)
- 最好的狀況下,時間複雜度爲O(n)
- 優先級隊列
-
必會技能:
-
課後習題總結:
- 區分一個序列是否爲最大堆
- 畫出一個完整的MAX-HEAPIFY流程
第五章 快速排序
-
快速排序
-
時間複雜度
- 最好Θ(nlgn)
- 平均Θ(nlgn)
- 最壞Θ(n2)
- 知道分治的過程————以一個數作分治,分紅兩組
- 掌握快排的手動作法
- 有一個關於每次都從1/10位置分隔的狀況下仍爲nlgn的證實
-
隨機快排
- 關鍵:用隨機來避免出現Worst case
- 實際表現是最快的排序
-
時間複雜度
- 平均Θ(nlgn)
- 最壞Θ(n2) (僅在理論上存在)
-
課後習題總結
- 若快排數組中元素都同樣,時間複雜度是多少?
- 答:這是Worst Case 因此是Θ(n2)
第六章 線性時間排序
- BDD證實基於比較排序最壞狀況的最小量級是nlgn
-
計數排序
- 計數排序是一種穩定排序
- 時間複雜度Θ(k+n) ,在k與n同一數量級時,該複雜度爲O(n)
-
關鍵:被排序的n個數在0~k之間
- 範圍不能超過數的個數的量級
- 若這n個數的範圍是n^2,則時間複雜度再也不是O(n),而是O(n^2)
-
掌握計數排序的完整過程,能夠手跑
- 建立一個容量爲k的數組C,並將全部元素置零
- 遍歷原數組A,在C中對應的位置+1
- 遍歷數組C,從第2個元素開始的全部元素的值依次用前一個元素與當前元素的和替換。
- 逆序遍歷A,拿到元素a,在C中查找其位置(即C中元素對應的數值)在數組B中的對應位置放入a便可。同時將C中的那個數據-1
-
基數排序
- 掌握基數排序的完整過程,能夠手跑
- 基數排序的特色:利用穩定排序的特色,從低位到高位按位排序
-
時間複雜度
- Θ(d T(n))
- 在每位計算使用計數排序的時候,時間複雜度爲Θ(n)
-
桶排序
- 掌握桶排序的完整過程,能夠手跑
- 主要針對均勻分佈的數,利用哈西,靠散列的過程完成排序
- 要點:相似於計數排序,爲待排序數組提供若干個區間,將各個待排序的數放進區間內,完成區間內排序的同時,就獲得了一個完整的排序結果。
-
算法小結

-
課後習題總結
第七章 中位數和順序統計
- 找到最大值/最小值的方法:找到最值Θ(n),從頭至尾遍歷,每一步記下當前的最值,結果就是最後的結果
-
查找第i個元素的隨機算法
- 存在Worst Case能夠在線性時間完成計算的算法
-
瞭解PARTITION函數的做用及原理
- 該函數利用隨機數,拿到一個區間內的某數a,運行一次partition後,能保證以a爲界將原區間分爲兩個部分,選這兩個部分中的一部分繼續partition
- 優化後的partition主要在隨機拿到劃分元素上下功夫,經過將全部元素5個一組分紅小組,組內找出中位數,用全部的中位數再找出中位數a後,以a爲界劃分兩個部分,不斷循環,這樣能保證劃分的質量。
第八章 動態規劃(DP)
-
動態規劃問題的四個基本步驟
- 肯定最優解的結構。(DP的必要條件)
- 遞歸定義最優解的值。
- 自底向上計算解的值。
- 利用計算獲得的信息構造最優解。
-
裝配線調度問題
- 關鍵:問題的最優解包含其子問題的最優解
-
遞推關係式

-
矩陣鏈乘
- 關鍵:拆分後的矩陣鏈也要以最少的計算次數才能獲得正確的結果
-
遞推關係式

-
示意圖

-
DP問題的要素:最優子結構
- 有向圖中兩節點的最短路徑長度是有最優子結構的
- 有向圖中兩節點的最長路徑長度沒有最優子結構
- 最短路徑長度與最長路徑長度的區別是是子問題是否獨立。
-
自上而下與自底向上之間的比較
-
自上而下的遞歸形式算法
-
自底向上的動態規劃算法
- 沒有重複計算,但可能存在多餘計算,即計算並不會用到的數據
-
備忘錄以及應用備忘錄後兩種形式算法的對比
- 備忘錄經過記錄計算過的子問題,避免了在自上而下進行遞歸計算時,重複計算的問題
-
自底向上的動態規劃方法
-
自上而下+備忘錄
-
最長公共子序列(Longest common subsequence/LCS)
- 暴力算法:查找全部子串,時間複雜度是指數級
-
DP求解LCS原理
- 兩字符串A(m)、B(n),若最後一個字符相同則必定在其某個最長公共子序列C內,故C的長度爲1+LCS(A(m-1),B(n-1))
- 兩字符串A(m)、B(n),若最後一個字符不相同,則C的長度爲max{LCS(A(m-1),B(n)),LCS(A(m),B(n-1))}
- 因爲上兩條,故LCS由AB某一子字符短的LCS組成,故具備最優子結構
-
DP求解LCS圖解

-
圖解的解釋:
-
最大子段和
-
DP求解最大子段和的原理
- 最大子段和必定是某個元素a加上了前面的某一個子段和或者是a元素自己。
-
DP求解數組A最大子段和過程
- B[0]=A[0]
- B[1…n]=max{B[1…n], B[0…n-1]+ B[1…n]}
- 遍歷B,其中的最值就是最大子段和
-
課後習題總結
- 修改原算法使其能順序輸出裝配結果
- 推演一個矩陣鏈乘的最優加括號方式
- 推演兩個字符序列的LCS
第九章 貪心算法
-
貪心策略
- 貪心選擇性質:貪心策略但願經過局部選擇最優達到全局最優的目的。可是並非全部狀況都能達到全局最優。
-
活動選擇問題
-
揹包問題
包含0-1揹包、分數揹包兩個子問題
- 討論目的:從兩種揹包問題中對比動態規劃與貪心算法
-
異同點
- 共同點:均有最優子結構,符合動態規劃問題的求解條件
-
不一樣點:針對同一物品肯定是否選擇狀況
- 分數揹包:性價比最高的,必定在最優子結構中,由於其餘的物品都達不到這種評價標準
- 0-1揹包:不肯定,須要對全部狀況予以討論
-
解決策略:
-
分數揹包:貪心算法
- 具體方法:把當前性價比最高的物品裝到不能再裝(沒有了或者包滿了)爲止
-
0-1揹包:DP
-
具體作法:刻畫最優子結構,標準DP作法

-
哈夫曼編碼
利用變長編碼使編碼長度大大減少,原理:頻率越高的字符,表示的編碼越短。
第十章 最短路徑算法
最短路徑算法包含單源最短路徑、每對結點間的最短路徑。。。。
-
關於最短路徑概念的討論
- 最短路徑知足最優子結構,即:一個最短路徑a中的任意兩點的最短路徑b必定在a的路徑中
- 三角不等式:對於全部的 u,v,x∈V, 如下不等式成立 δ(u,v) ≤δ(u,x)+δ(x,v)
- 含有負環的圖中,某些最短路徑可能不存在
- 單源最短路徑:求解從一個點到其餘全部點的最短路徑的集合
-
狄傑斯特拉算法(單源)
狄傑斯特拉算法本質上利用了貪心思想,不斷的更新當前最短路徑,用來處理不含負邊的圖
- 時間複雜度:O(E+VlgV)
-
算法流程:
- 把原點a加入圖中。
- 記錄全部從原點能到達的結點的路徑長度,其餘的記爲∞
-
重複如下幾步,直到全部節點都記錄在圖中
- 選出未記錄到圖中的路徑v最小的那個結點p
- 把結點p加入圖中
- 用vp+p到其餘結點的路徑長度與原記錄中的最短路徑對比,記下小的那個
-
無權圖的最短路徑算法(單源)
無權圖由狄傑斯特拉算法退化而來,經過廣度優先的的搜索模式記錄最短路徑
-
Bellman-Ford算法 (單源)
Bellman-Ford算法能夠處理含有負邊、負環的圖,若是存在負環,則能報告由環爲負環
- 時間複雜度:O(VE)
-
算法流程:
- 初始化全部結點,到各結點的最短路徑初始化爲∞
-
執行如下流程n-1次(n爲結點個數)
- 遍歷每個邊,若是經過這個邊能使目的結點的最短路徑更小,就更新它
- 再執行一次循環中的過程,如有更改的結點則說明存在負環。不然返回當前結果
- 特色:好寫,時間複雜度高
-
每對結點間最短路徑
- V次Dijkstra:O(VE+V^2lgV)
-
V次Bellman-Ford:O(V^2E)
-
每對結點間最短路徑第一種算法(矩陣「乘」)
- 原理:同時對全部節點同時進行一次Bellman-Ford操做
-
步驟:
- 證實:略
-
改進的矩陣「乘法」
- 每次都是對A進行這種乘法,能夠每次都計算A^2這種算法
- 原理:因爲利用三角不等式,因此三角不等式中的兩小段路徑不必定是1和k-1的關係。也多是m和n之間的關係。能夠作這種偷懶簡化。
-
每對結點間最短路徑第二種算法(Floyd)
- 歸納:從1個點開始不斷往圖中增長點,若是新加入的點可以對當前的最短路徑產生影響的話,就更新當前的最短路徑結果表;約束過哪些結點
-
遞歸式:

-
流程:
- 初始化一個矩陣存儲方式的V個邊的圖
-
循環下列步驟V次,記當前次數爲k
- 對每一條路徑判斷,被k分爲兩段的該路徑是否會獲得更小的結果,用較小值更新它
-
每對結點間最短路徑第三種算法(Johnson)
- 歸納:爲了利用Dijkstra算法,因而經過更改權值,消除負權值以知足Dijkstra。由於Dijkstra代價小
-
課後習題總結
- 推演一個Bellman-Ford算法
- 推演一個矩陣「乘」算法
- 推演一個Floyd算法
第十一章 回溯法&分支限界法
回溯法和分支限界法都是搜索搜索方式,當DP、貪心這些方法沒有辦法使用時,只能經過搜索來找到結果。搜索的方法主要包括這兩類。回溯法是一種深度優先的搜索方式
-
n皇后問題(回溯法)
- 解空間具備n!個n元組組成
-
算法步驟:
- 注意限界函數:不與其它皇后衝突
-
15迷問題(分支限界法)
-
子集合數(回溯法)
- 限界函數:既不超過目標數,剩下的數字和還大於距目標數的差距
-
01揹包(回溯法)
- 限界函數:還有可能(經過分數揹包計算剩下的產品價值)產生比當前的最優解好的狀況才繼續搜索
-
回溯法的通常方法
第十二章 NP問題與一些概念
-
可計算性
- 不是全部問題都是可計算的
- 普斯特競賽問題(不可求解)
- 有限步操做肯定一個給定的多元多項式是否有整數根問題(不可求解)
-
停機問題(不可求解)
-
NP徹底
- P:在肯定化的圖靈機上可在多項式級計算時間內求解的可斷定問題集合。
- EXP:在肯定化的圖靈機上可在指數級計算時間內求解的可斷定問題集合。
- NP:存在有效驗證算法的可斷定問題集合
-
NPC:NP集合中具備以下性質的問題:若該問題可被有效求解,則其求解方法可被用於有效求解其它NP徹底問題。
- TSP:找到可否在距離D內訪問N個城市
- 三色問題:用三個顏色爲地圖上色,要求鄰國顏色不同
- SAT:電路可知足性
-
如何面對NPC問題?若是一個問題是NP徹底問題,則咱們所設計的算法最多能同時作到如下三點中的兩點:
- 求解問題的最優解
- 在多項式級時間內求解
- 求解問題的任一實例