先来看看问题的来源,假设有这么一个数组:
1 | 2 | -5 | 4 | -2 | 3 | -3 | 4 | -15 |
我们要求出其中连续字数组的和的最大值 例如这么可以很明显看出 4+ –2 + 3 + –3 + 4 = 6 所有可能子数组的和的是最大值。
那我们应该如何实现呢:首先就是把所有可能的字数组的和求出来然后作比较就能得到最大值了,就像冒泡排序一样只是排序的对象需要经过一些处理:
1: public static void main(String[] args) {
2: int max = 0;
3: int a[] = { 1, 2, -5, 4, -2, 3, -3, 4, -15 };
4: for (int i = 0; i < a.length; i++) {
5: int sum = 0;
6: for (int j = i; j < a.length; j++) {
7: sum += a[j];
8: max = maxoftwo(max, sum);
9: }
10: }
11: System.out.println(max);
12: }
13:
14: private static int maxoftwo(int max, int sum) {
15: if (max > sum) {
16: return max;
17: } else {
18: return sum;
19: }
20: }
这里大概要运行时间为O(n2),这个时候再分析分析就会发现用分治算法会简便。我们将数组分为左右相等大小的子数组。
a | b |
这个时候用一个for循环就可以求出a,b中和的最大值
lmax(a) | rmax(b) |
这里还需要注意在两个数组的边界处相加也可能是最大值,左边从右往左的寻找最大和,右边从左往右寻找最大和,所以需要比较 lmax(a)+rmax(b),lmax(a),rmax(b)。
1: public static void main(String[] args) {
2: int max = 0;
3: int a[] = { 1, 2, -5, 4, -2, 3, -3, 4, -15 };
4: max=getmax(a,0,a.length-1);
5: System.out.print(max);
6: }
7:
8: private static int getmax(int[] a_sort, int start, int end) {
9: int mid=0,lmax=0,rmax=0,sum=0;
10: if(start >end){
11: return -1;
12: }
13: if(start == end){
14: return maxcompare(0,a_sort[1]);
15: }
16: mid = (start+end)/2;
17: for(int i=mid;i>=start;i--){
18: sum+=a_sort[i];
19: lmax=maxcompare(lmax, sum);
20: }
21: sum=0;
22: for(int i=mid+1;i<=end;i++){
23: sum+=a_sort[i];
24: rmax=maxcompare(rmax, sum);
25: }
26: return(maxcompare(maxcompare(lmax+rmax, getmax(a_sort, start, mid)),getmax(a_sort, mid+1, end)));
27: }
28:
29: private static int maxcompare(int i, int j) {
30: if(i>j){
31: return i;
32: }else{
33: return j;
34: }
35: }
对分治算法也还没有达到深深理解和灵活运用的境界,怎么才能让这种思想永存脑海呢?