最大和:
太经典的问题。不说了。
对于最大积问题:
由于负数的存在,我们不能简简单单只存一个当前最大值,我们还需要存当前最小值。我们令F(n)表示[0,n]区间内以d[n]为结尾的最大积,令G(n)表示[0,n]区间内以d[n]为结尾的最小积,d为原序列,那么有:
F(n + 1) = Max{F(n) * d[n + 1], d[n + 1], G(n) * d[n + 1]}
G(n + 1) = Min{F(n) * d[n + 1], d[n + 1], G(n) * d[n + 1]}
实际上,这个递推公式是重点。
01 | /// <summary> |
02 | /// 求解最大子段积,返回结果以及最优解的始末下标 |
03 | /// </summary> |
04 | /// <param name="seq">输入序列</param> |
05 | /// <param name="beginIndex">返回最优解的起始下标</param> |
06 | /// <param name="endIndex">返回最优解的结束下标</param> |
07 | /// <returns>最大子段积</returns> |
08 | public static long MaxSubMul( int [] seq, out int beginIndex, out int endIndex) |
09 | { |
10 | if (seq == null || seq.Length == 0 ) |
11 | throw new ArgumentNullException( "输入序列不能为空" ); |
12 | long maxMul = seq[ 0 ]; |
13 | beginIndex = endIndex = 0 ; |
14 | long curMaxMul = seq[ 0 ], curMinMul = seq[ 0 ]; |
15 | int curMinBeginIndex = 0 , curMaxBeginIndex = 0 ; |
16 | for ( int i = 1 ; i < seq.Length; i++) |
17 | { |
18 | long a = curMaxMul * seq[i], b = curMinMul * seq[i]; |
19 | long max, min; |
20 | int tmpMaxBeginIndex, tmpMinBeginIndex; |
21 | if (a > b) |
22 | { |
23 | max = a; |
24 | min = b; |
25 | tmpMaxBeginIndex = curMaxBeginIndex; |
26 | tmpMinBeginIndex = curMinBeginIndex; |
27 | } |
28 | else |
29 | { |
30 | max = b; |
31 | min = a; |
32 | tmpMaxBeginIndex = curMinBeginIndex; |
33 | tmpMinBeginIndex = curMaxBeginIndex; |
34 | } |
35 | if (seq[i] > max) |
36 | { |
37 | curMaxBeginIndex = i; |
38 | curMaxMul = seq[i]; |
39 | } |
40 | else |
41 | { |
42 | curMaxBeginIndex = tmpMaxBeginIndex; |
43 | curMaxMul = max; |
44 | } |
45 | if (seq[i] < min) |
46 | { |
47 | curMinBeginIndex = i; |
48 | curMinMul = seq[i]; |
49 | } |
50 | else |
51 | { |
52 | curMinBeginIndex = tmpMinBeginIndex; |
53 | curMinMul = min; |
54 | } |
55 | if (curMaxMul > maxMul) |
56 | { |
57 | maxMul = curMaxMul; |
58 | beginIndex = curMaxBeginIndex; |
59 | endIndex = i; |
60 | } |
61 | } |
62 | return maxMul; |
63 | } |
原文地址:http://fayaa.com/tiku/view/56/
http://my.oschina.net/Tristan/blog/33205
绝对值最小:
这题还是起源于微软的一道题:求数组中两个数,使得其差的绝对值最小。有人提出了将该题转化为连续子序列求和问题,结果 “求连续子序列,使得其和的绝对值最小” 这一问题反倒不好解决。这里想说的是,那何不把这问题转化回去,至少原问题 “求数组中两个数,使得其差的绝对值最小” 排序即可解决,N*LONG(N)。
均值最大/最小:
比如,求长度不小于K的连续子序列的最大平均值。百度之星2011,B组的第三题即是以该题为原型。简单的方法O(N^2)可解决,但有人提出了O(N)的神奇方法,不得不佩服并拜读一下:《浅谈数型结合思想在信息学竞赛中的应用》作者:周源。