每日一记,今天开始

从今天开始每天争取自己手写一两个小程序,即使是从书上看的,或者从网上学的,都自己手动地把代码打出来,贴在这里。

培养自己这个习惯,尽最大可能坚持下来。

水滴石穿,绳锯木断。

2014年9月10日

今天学习的是:求最大子序列和

有三种算法:

1 复杂度为O(N2)

 1 package findmaxsub;
 2 
 3 //求最大子序列和算法1:相当是遍历了一遍
 4 
 5 public class FindMaxSu {
 6 
 7     public static void main(String[] args) {
 8         // TODO Auto-generated method stub
 9         int[] a = new int[] {4,-3,5,-2,-1,2,6,-2,10};
10         System.out.println(findMax(a));
11 
12     }
13     private static int findMax(int [] array){
14         int maxSum = 0;
15         for(int i=0;i<array.length;i++){
16             int sum=0;
17             for(int j=i;j<array.length;j++){
18                 sum+=array[j];
19                 if(sum>maxSum){//注意这个if的位置
20                     maxSum=sum;
21                 }
22             }    
23         }
24         return maxSum;
25     }
26 }

2 复杂度为O(NlogN)

 1 package findmaxsub;
 2 
 3 //寻找最大子序列和的算法2
 4 //基本思路:最大子序列和三种情况:出现在数据的左半部分,右半部分,跨越数据的中部从而位于左右两半部分之中
 5 //前两种情况用递归,后一种情况简单地用两个for循环就行了
 6 
 7 //分而治之的思想:divide-and-conquer
 8 //递归的思想
 9 //关键是处理第三种情况为什么能用两个简单的循环:因为子序列的头已经确定了,必须包含这个中间的元素
10 
11 public class FindMaxSub {
12 
13     /**
14      * @param args
15      */
16     public static void main(String[] args) {
17         // TODO Auto-generated method stub
18         
19         int[] arr = new int[]{4,-3,5,-2,-1,2,6,-2,10};
20         System.out.println(maxSub(arr,0,arr.length-1));
21     
22 
23     }
24     
25     private static int maxSub(int [] array,int left,int right){
26         if(left==right){
27             if (array[left]>0)
28                return array[left];
29             else
30                return 0;
31         }
32         int center= (left+right)/2;
33         //前两种情况用递归
34         int leftMax=maxSub(array,left,center);
35         int rightMax=maxSub(array,center+1,right);
36         
37         //后一种情况用两个for循环
38         int leftBorderMax=0; int leftBorderSum=0;
39         for(int i=center;i>=left;i--){
40             leftBorderSum+=array[i];
41             if(leftBorderSum>leftBorderMax){
42                 leftBorderMax=leftBorderSum;
43             }
44         }
45         int rightBorderMax=0; int rightBorderSum=0;
46         for(int i=center+1;i<=right;i++){
47             rightBorderSum+=array[i];
48             if(rightBorderSum>rightBorderMax){
49                 rightBorderMax=rightBorderSum;
50             }
51         }
52         
53         return max3(leftMax,rightMax,leftBorderMax+rightBorderMax);
54         
55     }
56     
57     private static int max3(int a, int b, int c){
58         int n=a>b?a:b;
59         return c>n?c:n;
60     }
61 
62 }

3 复杂度为O(N)

 1 package findmaxsub;
 2 //求最大子序列和算法3:
 3 //这个算法最巧妙,时间运行最小
 4 //基于的思想:任何最大子序列的起点项不可能为负数,那么任何负的子序列不可能是最大子序列的前缀
 5 //所以只要前面的累积和为负数了,就可以重新选择开头了
 6 
 7 public class findMaxSubb {
 8 
 9     /**
10      * @param args
11      */
12     public static void main(String[] args) {
13         // TODO Auto-generated method stub
14         int [] arr = new int[]{4,-3,5,-2,-1,2,6,-2};
15         System.out.println(findMax(arr));
16 
17     }
18     private static int findMax(int[] arr){
19         int sum=0,maxSum=0;
20         for(int i=0;i<arr.length;i++){
21             sum+=arr[i];
22             if(sum<0)
23                 sum=0;
24             if(sum>maxSum){
25                 maxSum=sum;
26             }
27         }
28         return maxSum;
29     }
30 
31 }
原文地址:https://www.cnblogs.com/ivywenyuan/p/3965073.html