一道動態規劃題的分析。題目** leetcode——53.最大子序和
給定乙個整數陣列 nums ,找到乙個具有最大和的連續子陣列(子陣列最少包含乙個元素),返回其最大和。
示例:
輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。
複製**
高階: 如果你已經實現複雜度為 o(n) 的解法,嘗試使用更為精妙的分治法求解。
在分析如何使用動態規劃求解該問題前,我們先簡單了解下什麼是什麼是動態規劃(dp)。
動態規劃的適合解決的問題應該符合「乙個模型三個特徵」。
乙個模型指的是多階段決策最優解模型。指的是要經歷多個決策階段,每個決策對應多個狀態。然後我們從中找出一組能夠產生最優解的決策序列。
最優子結構
後面的決策可以通過前面的決策推導出。比如說最經典的0-1揹包問題,我們依次把物品放入揹包(或不放入)揹包。當進行到第 n 次決策(是否將第 n 個物品放入書包)時,前面的第 n - 1 已經決定好的多種決策(前面不同決策序列最終在 n - 1 次決策時給出了所有可以達到的重量),不會因為第 n 次的決策發生改變。
無後效性
一旦某個階段 a 的決策結束後,後面階段進行決策時,就不用考慮到階段 a 是如何推導出來的。我們只需要用到它的最終得到的決策序列。
重複子問題
不同的決策序列,在到達第 n 次決策結束後,可能會產生重複的狀態。比如假設依次要放入揹包的物品的重量分別為 2、4、2、3。 我們進入決策是否放入第3個物品的階段時,就會出現 「放入第1、3個物品和只放入第2個物品的兩組決策序列達到相同的重量」。這就是重複的狀態,可能會發生也可能不會發生。
1. 狀態轉移表法
動態規劃能解決的問題,都可以用回溯法的暴力搜尋解決。所以我們可以先用簡單的回溯演算法去試著去解決,從中找到規律,畫出遞迴樹。
當我們發現重複子問題時,一是可以使用回溯+「備忘錄」的方法。所謂備忘錄,就是我們會把 f(n) 的結果用雜湊表儲存起來(回溯經常用到遞迴函式),當又一次呼叫 f(n) 時,就直接取出快取起來的結果,以減少重複計算。二是這裡說的狀態表轉移表法。
通常狀態表是二維度的。每行代表著每乙個階段決策後的多個狀態。這個二維陣列會一行一行地進行填充,直到達到滿足結束狀態的情況(比如0-1揹包問題就是重量剛好達到揹包最大承重,或者n個物品都進行了決策,即完成了第 n 次決策)。這時我們只需要從最終的階段找出最終結果即可(揹包問題是從後往前找出乙個重量最大的值)
2. 狀態轉移方程法
關鍵在於找出狀態轉移方程。根據最優子結構,寫出遞迴公式,也就是所謂的狀態轉移方程。
那麼我們開始著手分析問題了。
首先我們試著用狀態轉移表法來做這道題。
以 [-2,1,-3,4,-1,2,1,-5,4] 為例進行分析,我們畫個遞迴樹分析一下。
(i, sum)。i 代表 第 i 個階段的決策,具體做的決策是:是選擇當前的元素為新的子陣列的起點,還是讓當前元素作為原來子陣列的後繼陣列元素。具體邏輯如下圖:
每個階段我們都會拿到決策後的兩種連續子陣列的和,我們會把它們和上一次階段的最大和比較,取出最大的值。
這裡要注意的是,當我們要選擇決策後的兩種情況的其中一種情況和大的情況,進行下一次遍歷,另一種情況是不需要進行下次的遞迴的。因為總和小的情況下的陣列,和後面的陣列相加時,必然比總和大的情況的總和要小,所以不需要進行接下來的遞迴。
var maxsubarray = function(nums)
return max;
};複製**
演算法 最大連續子陣列和
題目描述 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整數均為負數時定義子段和為0,依此定義,所求的最優值為 max,1 i j n 例如,當 a 1 a 2 a 3 a 4 a 5 a 6 a 7 1,2,11...
最大連續子串行和
最大連續子串行和問題是個很老的面試題了,最佳的解法是o n 複雜度,當然其中的一些小的地方還是有些值得注意的地方的。這裡還是總結三種常見的解法,重點關注最後一種o n 的解法即可。需要注意的是有些題目中的最大連續子串行和如果為負,則返回0 而本題目中的最大連續子串行和並不返回0,如果是全為負數,則返...
最大連續子陣列和
題目描述 輸入乙個整形陣列,陣列裡有正數也有負數。陣列中連續的乙個或多個整數組成乙個子陣列,每個子陣列都有乙個和。求所有子陣列的和的最大值,要求時間複雜度為o n 例如輸入的陣列為 1,2,3,10,4,7,2,5 和最大的子陣列為 3,10,4,7,2 因此輸出為該子陣列的和18。思路 採用貪婪法...