算法設計總述

算法設計複習筆記


引言

穩定匹配問題

現在有N位男生和N位女生,每個男生都對N個女生的喜歡程度做了排序,每個女生都對N個男生的喜歡程度做了排序,現在需要確定一個穩定的約會狀態。

穩定的定義:如果男生i和女生a牽手,但男生i對女生b更喜歡,而女生b發現,相比自己的男朋友j,她更喜歡男生i,則沒有力量阻礙男生i和女生b的私奔,這即是不穩定的。

設計一個算法解決穩定匹配問題,具體步驟參見鏈接。

算法

設計算法需要考慮到算法的正確性,有窮性和輸出。也即正確性,有窮性,可行性,0或多個輸入,一或多個輸出。

算法設計步驟

  1. 如何從一個實際的問題中抽取出具有本質性的問題描述。
  2. 能夠設計有效的算法解決問題。
  3. 分析算法的步驟及最後的結果。
  4. 能夠以小見大,用理論來解釋一些現象。

區間調度問題

可用貪心算法求解。

帶權的區間調度問題

可用動態規劃求解。具體步驟參見鏈接

二分匹配問題

選擇性的回溯,歸納的建立越來越大的匹配;這種處理叫做增廣。網絡流問題中,增廣構成了其中的核心要素。

最大獨立集問題

獨立集問題稱爲NP完全這一大類問題中的一個。
NP完全問題:Non-deterministic Polynomial(多項式複雜程度的非確定性問題)。
驗證和求解在難度上有很大的差別。

競爭的便利店選址問題

PSPACE完全問題類。
PSPACE完全問題嚴格難於NP完全問題。
PSPACE完全的概念涉及到對策策略,規劃,人工智能領域的基本課題。


算法分析基礎

什麼叫一個算法好?運行有效率?

定義效率1:當實現一個算法時,如果它在真實的實例上運行的快,那麼這個算法是有效的。

缺點:平臺,實例,輸入規模。

定義效率2:在分析的層次上,如果一個算法與蠻力搜索比較,最壞情況下達到質量上更好的性能,就說這個算法是有效的。

問題:什麼是質量上更好?

定義效率3:如果一個算法有多項式運行時間,稱爲這個算法是有效的。

  • 來自於數學形式和經驗證據。
  • 不絕對反映真實的運行時間。
  • 符合實際情況的合理近似。

多項式時間:一個算法被稱爲是多項式時間的,當且僅當滿足以下條件:

  • 當算法輸入的規模增長時,算法運行時間是多項式有界的。
  • 即存在常數c>0d>0 ,使得對於每一個規模爲N的輸入實例,算法的運行時間不超過cNd

定義效率的意義

有利於一般性的研究:

  • 清楚的表達:對某個問題不存在有效的算法。
  • 算法的研究轉入高質量科學的先決條件。
  • 問題具有固有的計算可解性的層次:
    • 某些能夠被有效地求解。
    • 某些不能夠被有效地求解。

爲什麼需要增長的漸進階這樣一個概念?

  • 得到一個準確的界是很困難的。
  • 目標是識別類似行爲算法的大類,按照粗粒度進行分析。
  • 算法執行的步數可能依賴於所使用的語言。

定義O,Ω和Θ,希望以不受常數因子和低項影響的方式表達運行時間的增長率

漸進的上界O:

  • 如果存在常數c>0n0>0 ,使得對所有n>n0 ,有T(n)c·f(n) ,那麼T(n)O(f(n)) 的。
  • f(n)T(n) 的漸進上界。
  • 要求存在一個對所有n有效的常數c。

漸進的下界Ω:

  • 如果存在常數ε>0n0>0 ,使得對所有n>n0 ,有T(n)ε·f(n) ,那麼T(n)Ω(f(n)) 的。
  • f(n)T(n) 的漸進下界。
  • 要求存在一個對所有n有效的常數ε。

漸進的緊Θ:

  • 如果T(n) 既是O(f(n)) 且也是Ω(f(n)) 的,我們就說T(n)Θ(f(n)) 的。
  • f(n) 是關於T(n) 的一個漸進的緊的界。

示例

亞線性時間

給定一個排好序的含有n個數的數組A,我們想確定一個給定的數p是否屬於這個數組。

採用二分查找算法。

時間複雜度:O(logn)

線性時間

計算n個數a1an 中的最大數。
歸併兩個排好序的數表。

時間複雜度:O(n)

O(nlogn) 階時間

快速排序。
快速傅里葉變換。
歸併排序。
堆排序。

平方時間

平面上給定n個點,由(x,y)表示座標。找最鄰近的點對。

時間複雜度:O(n2)

立方時間

給定集合S1Sn ,均爲{12n} 的子集,求這些子集中是否有某對子集是不相交的。

時間複雜度:O(n3)

O(nk) 階時間

給定的n個結點的輸入圖,確定是否有一個大小爲k的獨立集。

時間複雜度:O(k2nk/k!)=O(nk)

指數時間

給定一個圖,需要找一個最大規模的獨立集。

時間複雜度:O(n22n)

n!時間

穩定匹配問題的窮舉搜索。
巡迴售貨員問題。

時間複雜度:O(n!)


圖的表示:鄰接矩陣,鄰接鏈表。

路徑:無向圖G=(V,E)中,如下結點序列v1vk ,其中vivi+1 是E中的一條邊,則此結點序列被稱爲從v1vk 的路徑。

簡單路徑:如果一條路徑所有的結點都是相互不相同的,就稱爲簡單的。

連通:如果對於無向圖中任意兩個頂點u,v都存在一條路徑,那麼無向圖被稱爲是連通的。

圈:路徑v1vk 被稱爲一個圈,如果v1=vkk>2 ,而且前k-1個頂點兩兩不同。

樹:一個無向圖被稱爲是樹,如果它是連通的而且沒有圈。

鄰接矩陣

佔用O(n2) 的空間;檢查給定的邊是否出現在圖中,時間複雜度爲O(1)

鄰接鏈表

佔用O(m+n) 的空間,m爲邊的數目;檢查給定的邊是否出現在圖中,時間複雜度爲O(n)

寬度優先搜索

用隊列來維護即將被處理的節點。

深度優先搜索

用棧來維護即將被處理的節點。

二分性測試

如果一個圖時二部圖,那麼它不可能包含一個奇圈。

寬度優先搜索,G中沒有邊與同一層的兩個結點相交。

拓撲排序

有向無圈圖DAG。

如果G有一個拓撲排序,那麼G是一個DAG。

在每一個DAG中,存在一個沒有輸入邊的結點。

每次取那個沒有輸入邊的結點,加入拓撲排序。


貪心算法

一個算法時貪心的,如果:

  • 此算法時通過一些小的步驟來建立一個解。
  • 在每一步根據局部情況選擇一個決定。
  • 使得某些主要的指標能得到優化。

一個問題可以被貪心算法求解

  • 問題本身結果有關的一些性質。
  • 存在一個局部判斷規則。
  • 可以用來構造問題的最優解。

兩種基本方法證明一個問題能夠用貪心算法求得最優解

  • 貪心算法領先
    • 每一步都比其他的算法好。
    • 證明產生了一個最優解。
  • 交換論證
    • 考慮對這個問題的任何可能解。
    • 把它轉換成由貪心算法找到的解。
    • 不影響解的質量。
    • 證明貪心算法找到了一個至少與其他解一樣好的解。

區間調度問題

每一次選擇儘早結束的需求。

  • 按結束順序排序。
  • 每次選擇第一個區間,按次序迭代。

時間複雜度:O(nlogn)

區間劃分

沒看懂。

最小延遲調度

保證具有最早截止時間的任務最早完成。

  • 按照結束時間增長的次序排序。
  • 最早截止時間優先。

最優超高速緩存

簡化調度:在第i步有對d的需求;d不在超高速緩存中,考慮在第i步只放入項d的調度。

一個圖的最短路徑

Dijkstra算法。

最小生成樹問題

Kruskal算法。
反向刪除算法。
Prim算法。

聚類

最大間隔聚類

  • 定義距離
  • 按照距離增加的次序增加邊
  • 如果已經屬於同一個聚類則不添加,每一添加一條橫跨兩個不同連通分支的邊。

單鏈聚類

  • 定義距離。
  • 最小生成樹算法。
  • 刪除k-1條最貴的邊。

哈夫曼編碼

採用優先隊列(堆實現):每次插入,取出最小元素(O(logk) ),總運行時間(O(klogk) )。


動態規劃

貪心算法

  • 利用局部最優化原理,逐漸建立起完整的最優解。
  • 構成算法設計最自然的方法。
  • 對人們碰到的大多數問題,實際困難不在於確定幾個貪心策略中哪一個是正確的,而是事實上可能不存在有效的貪心算法。

動態規劃

  • 把事情分解爲一系列子問題。
  • 對越來越大的子問題建立正確的解。
  • 隱含的探查所有可行解的空間:
    • 穿過問題可行解的指數規模集合。
    • 不必明確檢查所有的解。

帶權的區間調度

詳細步驟參見鏈接

動態規劃原理

思路一

  • 設計一個(指數時間的)遞歸算法。
  • 通過備忘錄轉換成一個有效的遞推算法。
  • 利用全局數組來記錄遞歸函數值。

思路二

  • 在子問題上迭代,而不是遞歸地計算解。

動態規劃類型問題

  • 只存在多項式個子問題。
  • 容易從子問題的解計算初始問題的解。
  • 子問題從“最小”到“最大”存在自然的順序關係。
    • 與一個容易計算的遞推式相聯繫。
    • 允許更小的子問題來確定一個子問題的解。

動態規劃過程

  • 刻畫最優解的結構。
  • 構造最優值的遞歸關係表達式。
  • 按照自底向上或自頂向下的方式計算最優值。
  • 構造最優解。

分段的最小二乘

我賭不考,沒看。

揹包問題

if wi > w
    OPT(i,w) = OPT(i-1,w)
else
    OPT(i,w) = max{
        OPT(i-1,w),
        vi+OPT(i-1,w-wi)
        }

設計一個自底向上的算法,逐步填滿一個n·W的二維數組。也可以爲(n+1)·(W+1)。

時間複雜度:O(nW)

RNA二級結構

滿足:

  • 沒有尖的轉彎:每個對的兩段被至少四個插入的鹼基所分隔。
  • A-U,U-A,C-G,G-C。
  • 不交叉。
if j - i < 4
    OPT(i,j) = 0
else
    OPT(i,j) = max{
        OPT(i,j-1),
        1 + maxt{OPT(i,t-1) + OPT(t+1,j-1)}
        }
    //maxt遍歷所有的t,使得bt與bj是一對被允許的鹼基

序列比對

定義距離:

  • 空隙罰分δ。
  • 不匹配罰分αpq
if i = 0
    OPT(ij) = jδ
else if j = 0
    OPT(ij) = iδ
else
    OPT(ij) = min{
        α_xiyj + OPT(i-1,j-1),
        δ + OPT(i-1,j),
        δ + OPT(i,j-1)
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章