「手把手帶你學演算法」本週小結!(貪心演算法系列三)
本文 https://github.com/youngyangyang04/leetcode-master 已經收錄,裡面還有leetcode刷題攻略、各個型別經典題目刷題順序、思維導圖,可以fork到自己倉庫,有空看一看一定會有所收穫,如果對你有幫助也給一個star支援一下吧!
本週開始恢復了題目系列。
對於貪心,大多數同學都會感覺,不就是常識嘛,這算啥演算法,那麼本週的題目就可以帶大家初步領略一下貪心的巧妙,貪心演算法往往妙的出其不意。
週一
在貪心演算法:加油站中給出每一個加油站的汽油和開到這個加油站的消耗,問汽車能不能開一圈。
這道題目咋眼一看,感覺是一道模擬題,模擬一下汽車從每一個節點出發看看能不能開一圈,時間複雜度是O(n^2)。
即使用模擬這種情況,也挺考察程式碼技巧的。
for迴圈適合模擬從頭到尾的遍歷,而while迴圈適合模擬環形遍歷,對於本題的場景要善於使用while!
如果程式碼功力不到位,就模擬這種情況,可能寫的也會很費勁。
本題的貪心解法,我給出兩種解法。
對於解法一,其實我並不認為這是貪心,因為沒有找出區域性最優,而是直接從全域性最優的角度上思考問題,但思路很巧妙,值得學習一下。
對於解法二,貪心的區域性最優:當前累加rest[j]的和curSum一旦小於0,起始位置至少要是j+1,因為從j開始一定不行。全域性最優:找到可以跑一圈的起始位置。
這裡是可以從區域性最優推出全域性最優的,想不出反例,那就試試貪心。
解法二就體現出貪心的精髓,同時大家也會發現,雖然貪心是常識,有些常識並不容易,甚至很難!
週二
在貪心演算法:分發糖果中我們第一次接觸了需要考慮兩個維度的情況。
例如這道題,是先考慮左邊呢,還是考慮右邊呢?
先考慮哪一邊都可以! 就別兩邊一起考慮,那樣就把自己陷進去了。
先貪心一邊,區域性最優:只要右邊評分比左邊大,右邊的孩子就多一個糖果,全域性最優:相鄰的孩子中,評分高的右孩子獲得比左邊孩子更多的糖果
如圖:
接著在貪心另一邊,左孩子大於右孩子,左孩子的糖果就要比右孩子多。
此時candyVec[i](第i個小孩的糖果數量,左孩子)就有兩個選擇了,一個是candyVec[i + 1] + 1(從右孩子這個加1得到的糖果數量),一個是candyVec[i](之前比較右孩子大於左孩子得到的糖果數量)。
那麼第二次貪心的區域性最優:取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果數量,保證第i個小孩的糖果數量即大於左邊的也大於右邊的。全域性最優:相鄰的孩子中,評分高的孩子獲得更多的糖果。
區域性最優可以推出全域性最優。
如圖:
週三
在貪心演算法:檸檬水找零中我們模擬了買檸檬水找零的過程。
這道題目剛一看,可能會有點懵,這要怎麼找零才能保證完整全部賬單的找零呢?
但仔細一琢磨就會發現,可供我們做判斷的空間非常少!
美元10只能給賬單20找零,而美元5可以給賬單10和賬單20找零,美元5更萬能!
區域性最優:遇到賬單20,優先消耗美元10,完成本次找零。全域性最優:完成全部賬單的找零。
區域性最優可以推出全域性最優。
所以把能遇到的情況分析一下,只要分析到具體情況了,一下子就豁然開朗了。
這道題目其實是一道簡單題,但如果一開始就想從整體上尋找找零方案,就會把自己陷進去,各種情況一交叉,只會越想越複雜了。
週四
在貪心演算法:根據身高重建佇列中,我們再一次遇到了需要考慮兩個維度的情況。
之前我們已經做過一道類似的了就是貪心演算法:分發糖果,但本題比分發糖果難不少!
貪心演算法:根據身高重建佇列中依然是要確定一邊,然後在考慮另一邊,兩邊一起考慮一定會蒙圈。
那麼本題先確定k還是先確定h呢,也就是究竟先按h排序呢,還先按照k排序呢?
這裡其實很考察大家的思考過程,如果按照k來從小到大排序,排完之後,會發現k的排列並不符合條件,身高也不符合條件,兩個維度哪一個都沒確定下來。
所以先從大到小按照h排個序,再來貪心k。
此時區域性最優:優先按身高高的people的k來插入。插入操作過後的people滿足佇列屬性。全域性最優:最後都做完插入操作,整個佇列滿足題目佇列屬性。
區域性最優可以推出全域性最優,找不出反例,那麼就來貪心。
總結
「程式碼隨想錄」裡已經講了十一道貪心題目了,大家可以發現在每一道題目的講解中,我都是把什麼是區域性最優,和什麼是全域性最優說清楚。
雖然有時候感覺貪心就是常識,但如果真正是常識性的題目,其實是模擬題,就不是貪心演算法了!例如貪心演算法:加油站中的貪心方法一,其實我就認為不是貪心演算法,而是直接從全域性最優的角度上來模擬,因為方法裡沒有體現區域性最優的過程。
而且大家也會發現,貪心並沒有想象中的那麼簡單,貪心往往妙的出其不意,觸不及防!哈哈
下週依然還是貪心,敬請期待!
我是程式設計師Carl,可以找我組隊刷題,也可以在B站上找到我,本文leetcode刷題攻略已收錄,更多精彩演算法文章盡在公眾號:程式碼隨想錄,關注後就會發現和「程式碼隨想錄」相見恨晚!
循序漸進學演算法,認準「程式碼隨想錄」,Carl手把手帶你過關斬將!
相關文章
- 學一下貪心演算法-學一下貪心演算法演算法
- 貪心演算法演算法
- 貪心演算法(貪婪演算法,greedy algorithm)演算法Go
- 資料結構與演算法——貪心演算法資料結構演算法
- 五大常用演算法之三:貪心演算法演算法
- 常用演算法之貪心演算法演算法
- 貪心演算法Dijkstra演算法
- 9-貪心演算法演算法
- 【基礎演算法】(07)五大常用演算法之三:貪心演算法演算法
- 演算法基礎–貪心策略演算法
- Moving Tables(貪心演算法)演算法
- Python演算法:貪心策略Python演算法
- 演算法---貪心演算法和動態規劃演算法動態規劃
- 貪心演算法——換酒問題演算法
- 說說你對貪心演算法、回溯演算法的理解?應用場景?演算法
- 加油站問題(貪心演算法)演算法
- 貪心演算法篇——區間問題演算法
- 求最大子陣列(貪心演算法)陣列演算法
- 《演算法筆記》9. 培養貪心思維、貪心演算法深度實踐演算法筆記
- 【演算法•日更•第三期】最貼切的貪心演算法講解演算法
- 貪心演算法之無重疊區間演算法
- 活動選擇問題理解貪心演算法演算法
- 貪心演算法有時也很有用 - hashnode演算法
- 汽車加油問題 SDUT OJ 貪心演算法演算法
- leedcode-分發餅乾(貪心演算法)演算法
- Day27 貪心演算法part1演算法
- Day28 貪心演算法part2演算法
- Day31 貪心演算法part5演算法
- dfs與貪心演算法——洛谷5194演算法
- 演算法——貪心演算法解0-1揹包問題演算法
- 野生前端的資料結構練習(12)貪心演算法前端資料結構演算法
- [經典演算法]海盜分金問題sql求解(貪心演算法)演算法SQL
- 貪心演算法解硬幣找零問題演算法
- 馬踏棋盤之貪心演算法優化演算法優化
- 貪心演算法-找不重疊的區間段演算法
- 貪心演算法與動態規劃的區別演算法動態規劃
- 【LeetCode】貪心演算法–分發糖果(135)LeetCode演算法
- LeetCode解題記錄(貪心演算法)(二)LeetCode演算法