求解最優化問題得演算法通常需要經過一系列得步驟,每個步驟都面臨多種選擇。在許多最優化問題上使用動態規劃其實會有殺雞用牛刀的感覺。貪心演算法(greedy algorithm)保證每一步都作出當時看起來的最佳的選擇,換句話說就是保證區域性最優選。
確定問題的最優子結構
設計乙個遞迴演算法
證明我們每做乙個貪心選擇,則只剩下乙個子問題
證明貪心選擇是安全的
設計乙個遞迴演算法實現的貪心策略
將遞迴演算法轉為迭代演算法
明顯的通過1,2兩步驟的對比,我們知道貪心演算法是以dp為基礎的。
更一般地,我們可以按如下步驟設計貪心演算法:
證明做出貪心選擇後,原問題總是存在最優解,即貪心選擇總是安全的。
證明做出貪心選擇後,剩餘的子問題滿足性質:其最優解與貪心選擇組合即可以得到原問題的最優解,這樣就得到了最優子結構。
貪心選擇性質
做區域性最優選擇來構造全域性最優解。即進行選擇的時候只需要考慮當前問題中看來最優的選擇,而不必考慮子問題的解。
貪心演算法進行選擇時候可能依賴之前做出的選擇,單不依賴任何將來的選擇或者子問題的解。貪心演算法在進行第一次選擇之前不求解任何子問題。乙個動態規劃演算法通常是自底向上進行計算的,而乙個貪心演算法通常是自頂向下的。通過不斷的當前選擇來縮小問題的規模。
貪心選擇時候要進行眾多的選擇,這意味著可以改進貪心選擇,使其更為高效。可以通過排序跟改變資料結構(通常是優先佇列)做到這點。
最優子結構
如果乙個問題的最優解包含其子問題的最優解,則稱此問題具有最優子結構性質。最優子結構性質是dp與貪心演算法的關鍵。通過最優子結構我們可以設計出遞迴式來描述最優解值的方法。
貪心中的我們通常使用更為直接的最優子結構。要做的工作轉為證明:將子問題的最優解與貪心選擇組合在一起能生成原問題的最優解。(數學歸納法的應用)
輸入源:活動起始時間陣列s,活動結束時間陣列f,下標代表第幾個活動【注:活動集合 s = ,活動ai資料結構為含兩個時間的元組,乙個為活動開始時間,乙個為活動結束時間】。
目標:最大互相相容的活動集合
牛刀:dp思路
尋找乙個最優子結構:
令sij表示在ai結束之後開,並且在aj開之前結束的活動集合。假設存在aij子集是我們的解,並且包含活動ak。令aik = aij ∩ sik和akj = aij ∩ skj。 aij = aik u u akj
反證法可以證明aij必然包含子問題sik與skj的最優解。
遞迴定義最優解:
自頂向上演算法與構造最優解 -> 略
言歸正傳:貪心選擇
我們無需考慮最優子問題就可以選擇乙個活動加入最優解,原因很簡單從人的思維來說,每乙個步驟起始就是在選擇乙個活動,同樣是選擇乙個活動如果這個活動結束的時間越早那麼這個活動必然是最優解(反證法)。
1)遞迴貪心演算法
將活動按照活動結束時間進行排序,時間複雜度o(nlgn)。上偽**:
recursive-activity-selector(s, f, k, n) //k表示要求解的子問題sk, n表示問題規模
m = k + 1
while m <= n and s[m] < f[k]
m = m + 1 // sk中查詢第乙個相容活動ak的活動am,f陣列非遞減,fi <= fj (i < j)
if m <= n
return u recursive-activity-selector(s, f, m, n)
else return nil
2)迭代貪心演算法
recursive-activity-selector機會就是「尾遞迴」:結尾的自身遞迴呼叫接一次並集操作。而迭代形式更為直接:
greedy-activity-selector(s, f)
n = s.length
a =
k = 1
for m = 2 to n
if s[m] >= f[k]
a = a u
k = m
return a
3)總結
遞迴與迭代類似,在輸入活動已經按照結束時間排序好的前提下,兩者執行時間為θ(n)。
swift實現
續c
func greedyactivityselector(starts: [int], finishes: [int]) -> [int]
}return activities
}// test case
var s: [int] = [0, 1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12]
var f: [int] = [0, 4, 5, 6, 7, 9, 9, 10, 11, 12, 14, 16]
var a: [int] = greedyactivityselector(s, f)
for item in a
貪心 Swift實現
求解最優化問題得演算法通常需要經過一系列得步驟,每個步驟都面臨多種選擇。在許多最優化問題上使用動態規劃其實會有殺雞用牛刀的感覺。貪心演算法 greedy algorithm 保證每一步都作出當時看起來的最佳的選擇,換句話說就是保證區域性最優選。確定問題的最優子結構 設計乙個遞迴演算法 證明我們每做乙...
Swift實現UIScrollerView輪播
ios小白的第一篇部落格,最近做乙個專案,需要用swift實現uiscrollview的輪播功能,不允許使用第三方的庫,搜了很多 都沒找到合適的,最後幾經波折,在公司小姐姐的幫助下,終於逐步完善了 話不多說,直接上 以4張輪播為例 class viewcontroller uiviewcontrol...
Swift 中實現字典
雖然 swift 原生的字典型別實現的 很複雜 毫無疑問是為了效能 但是我們可以利用 swift 提供的工具寫出漂亮簡潔的實現。我們從乙個簡單的實現開始,並且逐步新增功能。我們簡要看一下字典的工作原理 它通過任意型別的關鍵字來設定和獲取值。這些值常常儲存在乙個陣列中,當然也可以儲存在樹型結構中。由於...