跳躍遊戲 ii
貪心演算法可以理解為一種特殊的動態規劃為題,擁有一些更加特殊的性質,可以進一步降低動態規劃演算法的時間複雜度。
來看幾道題目熟悉一下這種「不斷尋求區域性最優」的演算法。
輸入乙個非負整數陣列nums,陣列元素nums[i]表示的是:如果你站在位置 i ,最多能夠往前跳幾步。
現在你站在第乙個位置nums[0],試問你能否跳到陣列的最後乙個位置?
例:[1,2,3,4,5],可以
[1,2,0,0,4],不行
這題相對比較簡單一些吧,當然不要去用回溯,用回溯的話時間複雜度太高。
成功的方式太多了,但是失敗的方式只有乙個:有足夠多的0橫亙在其中,導致不論怎麼努力就是跳不過去。
我們哪幾個栗子來試一下吧:
[
0,····]
//點點點的意思是隨便你填什麼數字都無所謂了[1
,2,1
,0,···][2
,0,0
,···]
//還有啥特例嗎?
我們來分析一下上面的栗子(我們假設陣列有-1格,nums[-1] = 1,我們從nums[-1]開始):
第乙個栗子:在下標為0的時候遇到了絕望的0,從下標為-1的地方為此前能前進的最大步數1,無法跨越,終結。
第二個栗子:在下標為3的時候遇到了絕望的0,從下標為1的地方獲得了此前能前進的最大步數2,無法跨越,失敗。
第三個栗子:在下標為2的時候遇到了絕望的0,從下標為0的地方獲得了此前能前進的最大步數2,無法跨越,失敗。
這三個栗子中,我們能提取出什麼有效的資訊?
0
-(-1) =13
-1=2
2-0=
2
對吧。
還有呢?為什麼不變通一下,比如說例2中,不通過下標為2的點去中轉呢?因為中轉也無效啊。
那就是說我們要去嘗試著中轉。
這樣講可能會有點繞啊,我把例2改一下:[1,2,2,0],這不就活了嗎!
拿兩個例2來比對一下:
(以flag紀錄當前能夠到達的最遠距離)
[1,
2,1,
0,···]
//下標0最多到下標1,flag = 1;下標1最多到下標3,flag = 3;下標2最多到下標3,flag = 3;下標3,flag = 3;卒[1
,2,2
,0]//下標0:flag = 1;下標1:flag = 3;下標2:flag = 4
可以看到,當flag == 下標 的時候,就涼涼了。
所以,我們寫出**:
bool
canjump
(vector<
int>
& nums)
return farthest >= n-1;
}
跟上面差不多,但是這次保證你能跳到最後,問你最少跳幾次。
看著好眼熟啊,好像前面寫過一道這樣的題。換硬幣是吧。
去遞迴選取後續跳法裡面的最優,屬於一種:從後向前的解法,可以理解為從底層開始層序遍歷一棵樹。只不過我們後來通過備忘錄對這棵樹進行了剪枝,不然真的不忍直視啊。
貪心演算法是什麼?貪心演算法會選擇當下最有潛力的一步。
舉個例子:[2,3,1,2,5,1]
當你現在在下標0的位置,你可以跳兩步。動歸的話會遞迴去算這兩步到最終結果的最優步數,但是貪心演算法不這樣。
貪心演算法是每次盡可能多跳嗎?nonono,選擇當下最有潛力的:在座標1的位置,你有三個選擇;在座標2的位置,你只有乙個選擇,所以貪心演算法會讓你選擇跳到座標1。這就是貪心演算法的區域性最優(不要奇思妙想啥反例,要用貪心演算法,就要承擔它的失誤率)。
接下來,我們來寫**:
貪心演算法 C
貪心演算法 又稱貪婪演算法 是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的是在某種意義上的區域性最優解。貪心演算法並不保證會得到最優解,但是在某些問題上貪心演算法的解就是最優解。要會判斷乙個問題能否用貪心演算法來計算。第乙個問題 找零 假設商店老闆...
演算法 貪心演算法
把乙個複雜問題分解為一系列較為簡單的區域性最優選擇,每乙個選擇都是對當前解的乙個擴充套件,知道獲得問題的完整解。在解決問題的策略上目光短淺,只根據當前已有的資訊做出選擇,而且一旦做出了選擇,不管將來有什麼結果這個選擇都不會改變。換言之,貪心法並不是從整體最優考慮,它所做出的選擇只是在某種意義上的區域...
演算法 貪心演算法
集合覆蓋問題 旅行商問題等都屬於np完全問題,在數學領域上並沒有快速得到最優解的方案,非常適合用貪婪演算法。判斷方法 1.元素較少時,一般執行速度很快,但隨著元素數量增多,速度會變得非常慢 2.涉及到需要計算比較 所有的組合 情況的通常是np完全問題 3.無法分割成小問題,必須考慮各種可能的情況。這...