W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
「貪心算法 greedy algorithm」是一種常見的解決優(yōu)化問題的算法,其基本思想是在問題的每個(gè)決策階段,都選擇當(dāng)前看起來最優(yōu)的選擇,即貪心地做出局部最優(yōu)的決策,以期望獲得全局最優(yōu)解。貪心算法簡潔且高效,在許多實(shí)際問題中都有著廣泛的應(yīng)用。
貪心算法和動(dòng)態(tài)規(guī)劃都常用于解決優(yōu)化問題。它們之間存在一些相似之處,比如都依賴最優(yōu)子結(jié)構(gòu)性質(zhì),但工作原理是不同的。
我們先通過例題“零錢兌換”了解貪心算法的工作原理。這道題已經(jīng)在動(dòng)態(tài)規(guī)劃章節(jié)中介紹過,相信你對它并不陌生。
Question
給定
本題的貪心策略如圖 15-1 所示。給定目標(biāo)金額,我們貪心地選擇不大于且最接近它的硬幣,不斷循環(huán)該步驟,直至湊出目標(biāo)金額為止。
圖 15-1 零錢兌換的貪心策略
實(shí)現(xiàn)代碼如下所示。你可能會不由地發(fā)出感嘆:So Clean !貪心算法僅用十行代碼就解決了零錢兌換問題。
coin_change_greedy.cpp
/* 零錢兌換:貪心 */
int coinChangeGreedy(vector<int> &coins, int amt) {
// 假設(shè) coins 列表有序
int i = coins.size() - 1;
int count = 0;
// 循環(huán)進(jìn)行貪心選擇,直到無剩余金額
while (amt > 0) {
// 找到小于且最接近剩余金額的硬幣
while (i > 0 && coins[i] > amt) {
i--;
}
// 選擇 coins[i]
amt -= coins[i];
count++;
}
// 若未找到可行方案,則返回 -1
return amt == 0 ? count : -1;
}
貪心算法不僅操作直接、實(shí)現(xiàn)簡單,而且通常效率也很高。在以上代碼中,記硬幣最小面值為
然而,對于某些硬幣面值組合,貪心算法并不能找到最優(yōu)解。圖 15-2 給出了兩個(gè)示例。
圖 15-2 貪心無法找出最優(yōu)解的示例
也就是說,對于零錢兌換問題,貪心算法無法保證找到全局最優(yōu)解,并且有可能找到非常差的解。它更適合用動(dòng)態(tài)規(guī)劃解決。
一般情況下,貪心算法適用于以下兩類問題。
那么問題來了,什么樣的問題適合用貪心算法求解呢?或者說,貪心算法在什么情況下可以保證找到最優(yōu)解?
相較于動(dòng)態(tài)規(guī)劃,貪心算法的使用條件更加苛刻,其主要關(guān)注問題的兩個(gè)性質(zhì)。
最優(yōu)子結(jié)構(gòu)已經(jīng)在動(dòng)態(tài)規(guī)劃章節(jié)中介紹過,不再贅述。值得注意的是,一些問題的最優(yōu)子結(jié)構(gòu)并不明顯,但仍然可使用貪心算法解決。
我們主要探究貪心選擇性質(zhì)的判斷方法。雖然它的描述看上去比較簡單,但實(shí)際上對于許多問題,證明貪心選擇性質(zhì)不是一件易事。
例如零錢兌換問題,我們雖然能夠容易地舉出反例,對貪心選擇性質(zhì)進(jìn)行證偽,但證實(shí)的難度較大。如果問:滿足什么條件的硬幣組合可以使用貪心算法求解?我們往往只能憑借直覺或舉例子來給出一個(gè)模棱兩可的答案,而難以給出嚴(yán)謹(jǐn)?shù)臄?shù)學(xué)證明。
Quote
有一篇論文給出了一個(gè)
Pearson, David. A polynomial-time algorithm for the change-making problem. Operations Research Letters 33.3 (2005): 231-234.
貪心問題的解決流程大體可分為以下三步。
確定貪心策略是求解問題的核心步驟,但實(shí)施起來可能并不容易,主要包含以下原因。
為了保證正確性,我們應(yīng)該對貪心策略進(jìn)行嚴(yán)謹(jǐn)?shù)臄?shù)學(xué)證明,通常需要用到反證法或數(shù)學(xué)歸納法。
然而,正確性證明也很可能不是一件易事。如若沒有頭緒,我們通常會選擇面向測試用例進(jìn)行 Debug ,一步步修改與驗(yàn)證貪心策略。
貪心算法常常應(yīng)用在滿足貪心選擇性質(zhì)和最優(yōu)子結(jié)構(gòu)的優(yōu)化問題中,以下列舉了一些典型的貪心算法問題。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: