【L53】動態規劃求解最大子序和問題
阿新 • • 發佈:2021-07-18
Question
給定一個整數陣列 nums , 找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。
Anwser
當問題可以分解為彼此獨立且離散子問題時,可以考慮使用動態規劃來解決。
難點在於建模,即設計出動態規劃解決方案(找出前後子問題的關係,體現在程式碼裡就是計算公式)。
本題中的關係:
// 暴力求解,時間複雜度是O(N^3) // func maxSubArray(nums []int) int { // sum := nums[0] // for i := 0; i < len(nums); i++ { // for j := i; j < len(nums); j++ { // var s int // for idx := i; idx <= j; idx++ { // s += nums[idx] // } // if s > sum { // sum = s // } // } // } // return sum // } // 暴力求解優化,時間複雜度是O(N^2) // 事實上,上面的程式碼有一些重複計算, // 這是因為相同字首的區間求和,即後一個區間的和=當前值+前一個區間的和。 // func maxSubArray(nums []int) int { // sum := nums[0] // for i := 0; i < len(nums); i++ { // var s int // for j := i; j < len(nums); j++ { // s += nums[j] // if s > sum { // sum = s // } // } // } // return sum // } // 動態規劃,時間複雜度是O(N) // https://leetcode-cn.com/problems/maximum-subarray/solution/zheng-li-yi-xia-kan-de-dong-de-da-an-by-lizhiqiang/ // func maxSubArray(nums []int) int { // if 0 == len(nums) { // return 0 // } // // 先計算每個子組的最大值 // idx2max := map[int]int{} // idx2max[0] = nums[0] // for idx:=1; idx<len(nums); idx++ { // if idx2max[idx-1] > 0 { // idx2max[idx] = nums[idx] + idx2max[idx-1] // } else { // idx2max[idx] = nums[idx] // } // } // // 找到子組的最大值即全域性最大值 // sum := idx2max[0] // for _, max := range idx2max { // if max > sum { // sum = max // } // } // return sum // } // 動態規劃優化,降低空間複雜度 func maxSubArray(nums []int) int { if 0 == len(nums) { return 0 } sum := nums[0] // 記錄全域性最大值 subMax := nums[0] // 只需要一個int變數儲存前面子組合的最大值 for idx := 1; idx < len(nums); idx++ { if subMax > 0 { subMax += nums[idx] } else { subMax = nums[idx] } if subMax > sum { sum = subMax } } return sum }
擴充套件
相關問題
1. 揹包問題。
2. 尋找最長公共子串、最長公共子序列。
相似問題
1. 旅行商問題。
2. 集合覆蓋問題。
屬於NP完全問題,需要使用貪婪演算法求取近似解。
作者:Standby — 一生熱愛名山大川、草原沙漠,還有妹子出處:http://www.cnblogs.com/standby/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。