------------------------------------maxsubsum.go------------------------------------------
package maxsubsum // 問題描述:最大子序列和 // 給定(有可能爲負的)整數A1A2,...,An,求sum(Ai,...,Aj)最大值(如所有整數均爲負數,則最大子序列和爲0) // -2,11,-4,13,-5,-2,答案爲20(從A2到A4) // 暴力枚舉所有情況 時間複雜度 o(n^2) 空間複雜度 o(1) func maxSubSum1(arr []int) (max int) { length := len(arr) for i := 0; i < length; i++ { tmpMax := 0 for j := i; j < length; j++ { tmpMax += arr[j] if tmpMax >= max { max = tmpMax } } } return } // 使用遞歸 將數組中間拆分,最大值可能出現在左半部分,或者右半部分,或者跨越左右兩部分 // 時間複雜度 o(NlogN) 空間複雜度 o(n) func maxSubSum2(arr []int) (max int) { size := len(arr) // 遞歸出口,子序列沒有元素或者只剩一個元素時結束遞歸 if size < 1 { return } if size == 1 { if arr[0] > 0 { max = arr[0] } return } // 遞歸計算左右兩部分的最大值 center := size / 2 maxSumLeft := maxSubSum2(arr[0:center]) maxSumRight := maxSubSum2(arr[center:]) // 計算可能跨越左右兩部分的最大值 // 從中間切分點向左,向右分別計算最大值,二者之和爲跨越中點的最大值 var leftMaxSum, leftTempMaxSum int for i := center - 1; i > -1; i-- { leftTempMaxSum += arr[i] if leftMaxSum <= leftTempMaxSum { leftMaxSum = leftTempMaxSum } } var rightMaxSum, rightTempMaxSum int for i := center; i < size; i++ { rightTempMaxSum += arr[i] if rightMaxSum <= rightTempMaxSum { rightMaxSum = rightTempMaxSum } } maxSumCenter := leftMaxSum + rightMaxSum // 從左最大值,右最大值,中間最大值中選擇最大值爲最終結果 if maxSumLeft > maxSumRight { if maxSumLeft > maxSumCenter { return maxSumLeft } else { return maxSumCenter } } else { if maxSumRight > maxSumCenter { return maxSumRight } else { return maxSumCenter } } } // 優化過的算法 // 從左到右依次掃描求和,如果某值爲負數,其不可能爲序列的起始,繼續判斷下一個值;某個子序列的和<0,則該序列不可能爲最大和子序列的一部分 // 時間複雜度 o(n 空間複雜度 o(1) func maxSubSum3(arr []int) (max int) { var tmpSum int for _, val := range arr { tmpSum += val if tmpSum > max { max = tmpSum } if tmpSum < 0 { tmpSum = 0 } } return }
--------------------------------------------maxsubsum_test.go-----------------------------------------------
package maxsubsum import ( "testing" "math/rand" "time" "fmt" ) type Data struct { Arr []int Max int } var data = []Data{ {[]int{-2, 11, -4, 13, -5, -2}, 20}, {[]int{4, -3, 5, -2, -1, 2, 6, -2}, 11}, } func TestMaxSubSum(t *testing.T) { for i,f:=range []func([]int)int{maxSubSum1,maxSubSum2,maxSubSum3}{ for _, item := range data { max := f(item.Arr) if max != item.Max { t.Errorf("method %d input %v expect %d but got %d \n", i,item.Arr, item.Max, max) } } } } func TestLargeScale(t *testing.T) { // 生成長度爲10萬的測試數組 rand.Seed(time.Now().UnixNano()) arr:=make([]int,100000) for i:=0;i<len(arr);i++{ flag :=1 if rand.Intn(3)==1{ flag=-1 } arr[i]=rand.Intn(1000)*flag } for i,f:=range []func([]int)int{maxSubSum1,maxSubSum2,maxSubSum3}{ start:=time.Now().UnixNano() max:=f(arr) end:=time.Now().UnixNano() fmt.Printf("方式%d 計算結果: %d 耗時:%d\n",i,max,end-start) } }