1
+ /*
2
+ * @Author: 百里
3
+ * @Date: 2020-02-12 17:16:16
4
+ * @LastEditTime: 2020-02-12 17:17:10
5
+ * @LastEditors: 百里
6
+ * @Description:
7
+ * @FilePath: \leetcode\10.动态规划\01.连续最大子数组之和.go
8
+ * @https://github.com/yezihack
9
+ */
10
+ package dp
11
+
12
+ import (
13
+ "fmt"
14
+ "testing"
15
+ )
16
+
17
+ //题目: 一维数组里有负数又有整数,求子数组连续求和最大.
18
+ //如[1, 2, -4, 2, 3], 连续求和最大是[2,3],和: 2+3=5
19
+
20
+ //方法一: 暴力法. 从0位置到尾都查看一遍,每计算一步都进行之前累加的数与当前数对比.并求出最大之和
21
+ func ContinueChildArraySum (arr []int ) int {
22
+ total := 0 //求得最终的和
23
+ for i := 0 ; i < len (arr ); i ++ {
24
+ sum := 0 //当前连续之和
25
+ for j := i ; j < len (arr ); j ++ { //从i到n之间寻找最大值.
26
+ sum += arr [j ] //累加
27
+ fmt .Printf ("sum:%d, total:%d, cur:%d\n " , sum , total , arr [j ])
28
+ //比较三者之间大小, 取最大值.
29
+ total = max3 (total , sum , arr [j ]) //三个元素中查找最大值.赋值给total变量.
30
+ }
31
+ }
32
+ return total
33
+ }
34
+ func TestContinueChildArraySum (t * testing.T ) {
35
+ if ret := ContinueChildArraySum ([]int {1 , - 5 , 2 , - 4 , 2 , 3 }); ret != 5 {
36
+ t .Errorf ("actual:%d, expect:%d\n " , ret , 5 )
37
+ }
38
+ if ret := ContinueChildArraySum ([]int {1 , 1 ,- 2 , 3 , 1 }); ret != 4 {
39
+ t .Errorf ("actual:%d, expect:%d\n " , ret , 4 )
40
+ }
41
+ if ret := ContinueChildArraySum ([]int {8 , - 8 , - 2 , - 2 , - 1 , - 1 }); ret != 8 {
42
+ t .Errorf ("actual:%d, expect:%d\n " , ret , 8 )
43
+ }
44
+ }
45
+
46
+ //方法二: 动态规划
47
+ //设置一个变量sum存储每一步的结果,如果当前值大于sum,则交换.
48
+ //再定义一个dp数组,存储当前最大的元素.
49
+ //时间O(n), 空间O(n)
50
+ func ContinueChildArraySumDp (arr []int ) int {
51
+ dp := make ([]int , len (arr )) //动态规划数组
52
+ sum := 0 //当前步骤之和
53
+ for i := 0 ; i < len (arr ); i ++ {
54
+ sum += arr [i ] //累加操作.
55
+ if sum < arr [i ] { //当前大于sum,才交换
56
+ sum = arr [i ]
57
+ }
58
+ if sum > dp [i ] { //如果大于DP值,则存储起来.
59
+ dp [i ] = sum
60
+ }
61
+ }
62
+ fmt .Println (dp )
63
+ max := 0 //查找dp数组,取出最大值.
64
+ for i := 0 ; i < len (dp ); i ++ {
65
+ if dp [i ] > max {
66
+ max = dp [i ]
67
+ }
68
+ }
69
+ return max
70
+ }
71
+ func TestContinueChildArraySumDp (t * testing.T ) {
72
+ if ret := ContinueChildArraySumDp ([]int {1 , - 5 , 2 , - 4 , 2 , 3 }); ret != 5 {
73
+ t .Errorf ("actual:%d, expect:%d\n " , ret , 5 )
74
+ }
75
+ if ret := ContinueChildArraySumDp ([]int {1 , 1 ,- 2 , 3 , 1 }); ret != 4 {
76
+ t .Errorf ("actual:%d, expect:%d\n " , ret , 4 )
77
+ }
78
+ if ret := ContinueChildArraySumDp ([]int {8 , - 8 , - 2 , - 2 , - 1 , - 1 }); ret != 8 {
79
+ t .Errorf ("actual:%d, expect:%d\n " , ret , 8 )
80
+ }
81
+ }
82
+ //方法三: 动态规划
83
+ //题目说, 有正有负, 连续之和必定大于0. 如果使用一个变量累加时,与当前元素还小则进行交换.
84
+ //再重头计算.将每一次计算的结果存储在一个额外地变量里.最终得到最优解.
85
+ func ContinueChildArraySumDpV2 (arr []int ) int {
86
+ var total , sum = 0 , 0 //定义一个total为最优解, sum为当前连续最优解的变量.
87
+ for i := 0 ; i < len (arr ); i ++ {
88
+ sum += arr [i ] //求连续最优解之和
89
+ if arr [i ] > sum { //如果当前值大于最优解则交换
90
+ sum = arr [i ] //交换
91
+ }
92
+ if sum > total { //如果最优解大于最终最优解则交换 .
93
+ total = sum
94
+ }
95
+ }
96
+ return total
97
+ }
98
+
99
+ func TestContinueChildArraySumDpV2 (t * testing.T ) {
100
+ if ret := ContinueChildArraySumDpV2 ([]int {1 , - 5 , 2 , - 4 , 2 , 3 }); ret != 5 {
101
+ t .Errorf ("actual:%d, expect:%d\n " , ret , 5 )
102
+ }
103
+ if ret := ContinueChildArraySumDpV2 ([]int {1 , 1 ,- 2 , 3 , 1 }); ret != 4 {
104
+ t .Errorf ("actual:%d, expect:%d\n " , ret , 4 )
105
+ }
106
+ if ret := ContinueChildArraySumDpV2 ([]int {8 , - 8 , - 2 , - 2 , - 1 , - 1 }); ret != 8 {
107
+ t .Errorf ("actual:%d, expect:%d\n " , ret , 8 )
108
+ }
109
+ }
110
+ func max3 (a , b , c int ) int {
111
+ max := a
112
+ if b > a {
113
+ max = b
114
+ }
115
+ if c > max {
116
+ return c
117
+ }
118
+ return max
119
+ }
0 commit comments