452.用最少數量的箭引爆氣球
-----------
什麼是貪心演算法呢?貪心演算法可以認為是動態規劃演算法的乙個特例,相比動態規劃,使用貪心演算法需要滿足更多的條件(貪心選擇性質),但是效率比動態規劃要高。
比如說乙個演算法問題使用暴力解法需要指數級時間,如果能使用動態規劃消除重疊子問題,就可以降到多項式級別的時間,如果滿足貪心選擇性質,那麼可以進一步降低時間複雜度,達到線性級別的。
什麼是貪心選擇性質呢,簡單說就是:每一步都做出乙個區域性最優的選擇,最終的結果就是全域性最優。注意哦,這是一種特殊性質,其實只有一部分問題擁有這個性質。
比如你面前放著 100 張人民幣,你只能拿十張,怎麼才能拿最多的面額?顯然每次選擇剩下鈔票中面值最大的一張,最後你的選擇一定是最優的。
然而,大部分問題明顯不具有貪心選擇性質。比如打鬥地主,對手出對兒三,按照貪心策略,你應該出盡可能小的牌剛好壓制住對方,但現實情況我們甚至可能會出王炸。這種情況就不能用貪心演算法,而得使用動態規劃解決,參見前文「動態規劃解決博弈問題」。
言歸正傳,本文解決乙個很經典的貪心演算法問題 interval scheduling(區間排程問題)。給你很多形如[start, end]
的閉區間,請你設計乙個演算法,算出這些區間中最多有幾個互不相交的區間。
int intervalschedule(int intvs) {}
舉個例子,intvs = [[1,3], [2,4], [3,6]]
,這些區間最多有 2 個區間互不相交,即[[1,3], [3,6]]
,你的演算法應該返回 2。注意邊界相同並不算相交。
這個問題在生活中的應用廣泛,比如你今天有好幾個活動,每個活動都可以用區間[start, end]
表示開始和結束的時間,請問你今天最多能參加幾個活動呢?顯然你乙個人不能同時參加兩個活動,所以說這個問題就是求這些時間區間的最大不相交子集。
ps:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部發布在 labuladong的演算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種演算法套路後投再入題海就如魚得水了。
這個問題有許多看起來不錯的貪心思路,卻都不能得到正確答案。比如說:
也許我們可以每次選擇可選區間中開始最早的那個?但是可能存在某些區間開始很早,但是很長,使得我們錯誤地錯過了一些短的區間。或者我們每次選擇可選區間中最短的那個?或者選擇出現衝突最少的那個區間?這些方案都能很容易舉出反例,不是正確的方案。
正確的思路其實很簡單,可以分為以下三步:
從區間集合 intvs 中選擇乙個區間 x,這個 x 是在當前所有區間中結束最早的(end 最小)。
把所有與 x 區間相交的區間從區間集合 intvs 中刪除。
重複步驟 1 和 2,直到 intvs 為空為止。之前選出的那些 x 就是最大不相交子集。
把這個思路實現成演算法的話,可以按每個區間的end
數值公升序排序,因為這樣處理之後實現步驟 1 和步驟 2 都方便很多:
現在來實現演算法,對於步驟 1,由於我們預先按照end
排了序,所以選擇 x 是很容易的。關鍵在於,如何去除與 x 相交的區間,選擇下一輪迴圈的 x 呢?
由於我們事先排了序,不難發現所有與 x 相交的區間必然會與 x 的end
相交;如果乙個區間不想與 x 的end
相交,它的start
必須要大於(或等於)x 的end
:
看下**:
public int intervalschedule(int intvs)
});// 至少有乙個區間不相交
int count = 1;
// 排序後,第乙個區間就是 x
int x_end = intvs[0][1];
for (int interval : intvs)
}return count;
}
下面舉例幾道 leetcode 題目應用一下區間排程演算法。
第 435 題,無重疊區間:
我們已經會求最多有幾個區間不會重疊了,那麼剩下的不就是至少需要去除的區間嗎?
int eraseoverlapintervals(int intervals)
第 452 題,用最少的箭頭射爆氣球:
其實稍微思考一下,這個問題和區間排程演算法一模一樣!如果最多有n
個不重疊的區間,那麼就至少需要n
個箭頭穿透所有區間:
只是有一點不一樣,在intervalschedule
演算法中,如果兩個區間的邊界觸碰,不算重疊;而按照這道題目的描述,箭頭如果碰到氣球的邊界氣球也會**,所以說相當於區間的邊界觸碰也算重疊:
所以只要將之前的演算法稍作修改,就是這道題目的答案:
int findminarrowshots(int intvs)
}return count;
}
_____________ 貪心演算法之區間排程問題
分析 拿到這道題目,首先要看清楚最終的題目要求,它的要求是參與盡可能多的工作,並不是說工作總時間最長。對於這題我們其實可以使用貪心演算法,就是不斷選取當前最優策略 我們不斷選取工作,其實可以有以下幾種思路進行選取,並進行聚反例來排除這種思路 1.在可選的工作中,選取開始時間最早的.反例 這種情況下先...
區間排程問題 貪心演算法
問題 有 n 項工作,每項工作分別在 s i 時間開始,在 t i 時間結束 對於每項 工作,你都有可以選擇參與與否。如果選擇了參與,那麼自始自終都必須全程參與。此外,參與工作的時間段不能重疊 即使是開始的瞬間和結束的瞬間的重疊也 是不允許的 include include include usin...
區間排程問題 貪心演算法
一 題目 區間排程問題 有n項工作,每項工作分別在si時間開始,在ti時間結束。對於每項工作,你都可以選擇參與與否。如果選擇了參與,那麼自始至終都必須全程參與。此外,參與工作的時間段不能重複 即使是開始的瞬間和結束的瞬間的重疊也是不允許的 你的目標是參與盡可能多的工作,那麼最多能參與多少項工作呢?1...