码迷,mamicode.com
首页 > 编程语言 > 详细

第2章 数字之魅——求数组的子数组之和的最大值

时间:2015-07-08 12:31:41      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

求数组的子数组之和的最大值

问题描述

技术分享

分析与解法

【解法一】

技术分享

具体代码如下:

 

 1 package chapter2shuzizhimei.maxsumsubarray;
 2 /**
 3  * 求数组的子数组之和的最大值
 4  * 【解法一】
 5  * @author DELL
 6  *
 7  */
 8 public class MaxSumSubArray1 {
 9     //求数组的子数组之和的最大值
10     public static double maxSum(double a[]){
11         double maxSum = a[0];
12         int i,j,k,n=a.length;
13         for(i=0;i<n;i++){
14             for(j=i;j<n;j++){
15                 double sum = 0;
16                 for(k=i;k<=j;k++){
17                     sum += a[k];
18                 }
19                 if(sum>maxSum)
20                     maxSum = sum;
21             }
22         }
23         return maxSum;
24     }
25     public static void main(String[] args) {
26         double a[]={1,-2,3,5,-3,2};
27         double b[]={0,-2,3,5,-1,2};
28         double c[]={-9,-2,-3,-5,-3};
29         System.out.println("求数组的子数组之和的最大值为:"+maxSum(a));
30         System.out.println("求数组的子数组之和的最大值为:"+maxSum(b));
31         System.out.println("求数组的子数组之和的最大值为:"+maxSum(c));
32 
33     }
34 
35 }

程序运行结果如下:

求数组的子数组之和的最大值为:8.0
求数组的子数组之和的最大值为:9.0
求数组的子数组之和的最大值为:-2.0

技术分享

代码如下:

 1 package chapter2shuzizhimei.maxsumsubarray;
 2 /**
 3  * 求数组的子数组之和的最大值
 4  * 【解法一】优化
 5  * @author DELL
 6  *
 7  */
 8 public class MaxSumSubArray2 {
 9     //求数组的子数组之和的最大值
10     public static double maxSum(double a[]){
11         double maxSum = a[0];
12         int i,j,k,n=a.length;
13         for(i=0;i<n;i++){
14             double sum = 0;    //优化修改
15             for(j=i;j<n;j++){
16                 sum += a[j];  //优化修改
17                 if(sum>maxSum)
18                     maxSum = sum;
19             }
20         }
21         return maxSum;
22     }
23     public static void main(String[] args) {
24         double a[]={1,-2,3,5,-3,2};
25         double b[]={0,-2,3,5,-1,2};
26         double c[]={-9,-2,-3,-5,-3};
27         System.out.println("求数组的子数组之和的最大值为:"+maxSum(a));
28         System.out.println("求数组的子数组之和的最大值为:"+maxSum(b));
29         System.out.println("求数组的子数组之和的最大值为:"+maxSum(c));
30 
31     }
32 
33 }

程序运行结果如下:

求数组的子数组之和的最大值为:8.0
求数组的子数组之和的最大值为:9.0
求数组的子数组之和的最大值为:-2.0

【解法二】

技术分享

技术分享

具体代码如下:

 1 package chapter2shuzizhimei.maxsumsubarray;
 2 /**
 3  * 求数组的子数组之和的最大值
 4  * 【解法二】递归求解
 5  * @author DELL
 6  *
 7  */
 8 public class MaxSumSubArray3 {
 9     //找两个数的最大值
10     public static double max(double a,double b){
11         return a>b ? a:b;
12     }
13     //求数组的子数组之和的最大值
14     public static double maxSum(double a[],int first, int last){
15         if(first==last)
16             return a[first];
17         int n = last-first+1;
18         double LmaxSum = maxSum(a, first, first+n/2-1); //左边的最大值
19         double RmaxSum = maxSum(a, first+n/2, last);  //右边的最大值
20         double maxSum = max(LmaxSum,RmaxSum);  //总的最大值
21         double maxSuml = a[first+n/2-1];  //横跨两段的左边段的最大值
22         double maxSumr = a[first+n/2];   //横跨两段的右边段的最大值
23         double sum = 0;
24         for(int i=first+n/2-1;i>=first;i--){
25             sum += a[i];
26             if(sum>maxSuml)
27                 maxSuml = sum;
28         }
29         sum = 0;
30         for(int i=first+n/2;i<=last;i++){
31             sum += a[i];
32             if(sum>maxSumr)
33                 maxSumr = sum;
34         }
35         maxSum = max(maxSum,maxSuml+maxSumr);
36         return maxSum;
37     }
38     public static void main(String[] args) {
39         double a[]={1,-2,3,5,-3,2};
40         double b[]={0,-2,3,5,-1,2};
41         double c[]={-9,-2,-3,-5,-3};
42         System.out.println("求数组的子数组之和的最大值为:"+maxSum(a,0,a.length-1));
43         System.out.println("求数组的子数组之和的最大值为:"+maxSum(b,0,b.length-1));
44         System.out.println("求数组的子数组之和的最大值为:"+maxSum(c,0,c.length-1));
45 
46     }
47 
48 }

程序运行结果如下:

求数组的子数组之和的最大值为:8.0
求数组的子数组之和的最大值为:9.0
求数组的子数组之和的最大值为:-2.0

【解法三】

技术分享

具体代码如下:

 

 1 package chapter2shuzizhimei.maxsumsubarray;
 2 /**
 3  * 求数组的子数组之和的最大值
 4  * 【解法三】动态规划
 5  * @author DELL
 6  *
 7  */
 8 public class MaxSumSubArray4 {
 9     //找两个数的最大值
10     public static double max(double a,double b){
11         return a>b ? a:b;
12     }
13     //求数组的子数组之和的最大值
14     public static double maxSum(double a[]){
15         int n = a.length;
16         double start[] = new double[n]; //start[i]表示从a[i]包含a[i]开始的最大和
17         double all[] = new double[n]; //all[i]表示从从a[i]到a[n-1]的一段中子数组之和的最大值
18         start[n-1] = a[n-1];
19         all[n-1] = a[n-1];
20         for(int i=n-2;i>=0;i--){
21             start[i] = max(a[i],a[i]+start[i+1]);
22             all[i] = max(start[i],all[i+1]);
23         }
24         return all[0];
25     }
26     public static void main(String[] args) {
27         double a[]={1,-2,3,5,-3,2};
28         double b[]={0,-2,3,5,-1,2};
29         double c[]={-9,-2,-3,-5,-3};
30         System.out.println("求数组的子数组之和的最大值为:"+maxSum(a));
31         System.out.println("求数组的子数组之和的最大值为:"+maxSum(b));
32         System.out.println("求数组的子数组之和的最大值为:"+maxSum(c));
33 
34     }
35 
36 }

程序运行结果如下:

求数组的子数组之和的最大值为:8.0
求数组的子数组之和的最大值为:9.0
求数组的子数组之和的最大值为:-2.0

 技术分享

具体代码如下:

 1 package chapter2shuzizhimei.maxsumsubarray;
 2 /**
 3  * 求数组的子数组之和的最大值
 4  * 【解法三】动态规划 优化(减少空间复杂度)
 5  * @author DELL
 6  *
 7  */
 8 public class MaxSumSubArray5 {
 9     //找两个数的最大值
10     public static double max(double a,double b){
11         return a>b ? a:b;
12     }
13     //求数组的子数组之和的最大值
14     public static double maxSum(double a[]){
15         int n = a.length;
16         double start; //start[i]表示从a[i]包含a[i]开始的最大和
17         double all; //all[i]表示从从a[i]到a[n-1]的一段中子数组之和的最大值
18         start = a[n-1];
19         all = a[n-1];
20         for(int i=n-2;i>=0;i--){
21             start = max(a[i],a[i]+start);
22             all = max(start,all);
23         }
24         return all;
25     }
26     public static void main(String[] args) {
27         double a[]={1,-2,3,5,-3,2};
28         double b[]={0,-2,3,5,-1,2};
29         double c[]={-9,-2,-3,-5,-3};
30         System.out.println("求数组的子数组之和的最大值为:"+maxSum(a));
31         System.out.println("求数组的子数组之和的最大值为:"+maxSum(b));
32         System.out.println("求数组的子数组之和的最大值为:"+maxSum(c));
33 
34     }
35 
36 }

程序运行结果如下:

求数组的子数组之和的最大值为:8.0
求数组的子数组之和的最大值为:9.0
求数组的子数组之和的最大值为:-2.0

  改进的算法不仅节省了空间,而且只有寥寥几行,却达到了很高的效率。我们还可以换一个写法:

 

 1 package chapter2shuzizhimei.maxsumsubarray;
 2 /**
 3  * 求数组的子数组之和的最大值
 4  * 【解法三】动态规划 优化(减少空间复杂度)
 5  * @author DELL
 6  *
 7  */
 8 public class MaxSumSubArray6 {
 9     //找两个数的最大值
10     public static double max(double a,double b){
11         return a>b ? a:b;
12     }
13     //求数组的子数组之和的最大值
14     public static double maxSum(double a[]){
15         int n = a.length;
16         double start; //start[i]表示从a[i]包含a[i]开始的最大和
17         double all; //all[i]表示从从a[i]到a[n-1]的一段中子数组之和的最大值
18         start = a[n-1];
19         all = a[n-1];
20         for(int i=n-2;i>=0;i--){
21             if(start<0)
22                 start = 0;
23             start = a[i]+start;
24             if(start>all)
25                 all = start;
26         }
27         return all;
28     }
29     public static void main(String[] args) {
30         double a[]={1,-2,3,5,-3,2};
31         double b[]={0,-2,3,5,-1,2};
32         double c[]={-9,-2,-3,-5,-3};
33         System.out.println("求数组的子数组之和的最大值为:"+maxSum(a));
34         System.out.println("求数组的子数组之和的最大值为:"+maxSum(b));
35         System.out.println("求数组的子数组之和的最大值为:"+maxSum(c));
36 
37     }
38 
39 }

程序运行结果如下:

求数组的子数组之和的最大值为:8.0
求数组的子数组之和的最大值为:9.0
求数组的子数组之和的最大值为:-2.0

 扩展问题

技术分享

(注:上面的i>j应改为i<=j)

技术分享

问题1 代码如下:

 1 package chapter2shuzizhimei.maxsumsubarray;
 2 /**
 3  * 求数组的子数组之和的最大值
 4  * 扩展问题1
 5  * @author DELL
 6  *
 7  */
 8 public class MaxSumSubArray7 {
 9     //找两个数的最大值
10     public static double max(double a,double b){
11         return a>b ? a:b;
12     }
13     //求数组的子数组之和的最大值,循环数组
14     public static double maxSum(double a[]){
15         int n = a.length;
16         double start; //start[i]表示从a[i]包含a[i]开始的最大和
17         double all; //all[i]表示从从a[i]到a[n-1]的一段中子数组之和的最大值
18         start = a[n-1];
19         all = a[n-1];
20         for(int i=n-2;i>=0;i--){
21             if(start<0)
22                 start = 0;
23             start = a[i]+start;
24             if(start>all)
25                 all = start;
26         }
27         double max1=a[n-1],max2=a[0],sum=0;
28         int i = n-1,j = 0;
29         //寻找以a[n-1]结尾的最大值
30         for(int k=n-1;k>=0;k--){
31             sum += a[k];
32             if(sum>max1){
33                 max1 = sum;
34                 i = k;
35             }
36         }
37         sum = 0;
38         //寻找以a[0]开始的最大值
39         for(int k=0;k<n;k++){
40             sum += a[k];
41             if(sum>max1){
42                 max2 = sum;
43                 j = k;
44             }
45         }
46         double max;
47         if(i<=j){
48             max = sum;
49         }else{
50             max = max1 + max2;
51         }
52         return max(all,max);
53     }
54     public static void main(String[] args) {
55         double a[]={1,-2,3,5,-3,2};
56         double b[]={0,-2,3,5,-1,2};
57         double c[]={-9,-2,-3,-5,-3};
58         double d[]={4,5,-9,-8,1,2,3};
59         System.out.println("求数组的子数组之和的最大值为:"+maxSum(a));
60         System.out.println("求数组的子数组之和的最大值为:"+maxSum(b));
61         System.out.println("求数组的子数组之和的最大值为:"+maxSum(c));
62         System.out.println("求数组的子数组之和的最大值为:"+maxSum(d));
63 
64     }
65 
66 }

程序运行结果如下:

求数组的子数组之和的最大值为:8.0
求数组的子数组之和的最大值为:9.0
求数组的子数组之和的最大值为:-2.0
求数组的子数组之和的最大值为:15.0

问题2 还能保持O(N)的时间复杂度

具体代码如下:

 1 package chapter2shuzizhimei.maxsumsubarray;
 2 /**
 3  * 求数组的子数组之和的最大值
 4  * 扩展问题1
 5  * @author DELL
 6  *
 7  */
 8 public class MaxSumSubArray8 {
 9     //找两个数的最大值
10     public static double max(double a,double b){
11         return a>b ? a:b;
12     }
13     //求数组的子数组之和的最大值,循环数组
14     public static double maxSum(double a[]){
15         int first,last; //记录最大数组的位置
16         int n = a.length;
17         double start; //start[i]表示从a[i]包含a[i]开始的最大和
18         double all; //all[i]表示从从a[i]到a[n-1]的一段中子数组之和的最大值
19         start = a[n-1];
20         first = n-1;
21         last = n-1;
22         all = a[n-1];
23         for(int i=n-2;i>=0;i--){
24             if(start<0){
25                 start = 0;
26                 last = i;
27             }
28             start = a[i]+start;
29             if(start>all){
30                 all = start;
31                 first = i;
32             }
33         }
34         if(first>last)
35             last = first;
36         double max1=a[n-1],max2=a[0],sum=0;
37         int i = n-1,j = 0;
38         //寻找以a[n-1]结尾的最大值
39         for(int k=n-1;k>=0;k--){
40             sum += a[k];
41             if(sum>max1){
42                 max1 = sum;
43                 i = k;
44             }
45         }
46         sum = 0;
47         //寻找以a[0]开始的最大值
48         for(int k=0;k<n;k++){
49             sum += a[k];
50             if(sum>max1){
51                 max2 = sum;
52                 j = k;
53             }
54         }
55         double max;
56         if(i<=j){
57             max = sum;
58         }else{
59             max = max1 + max2;
60         }
61         if(max>all){
62             if(i<=j)
63                 System.out.println("最大子数组的位置为整个数组!");
64             else
65                 System.out.println("最大子数组的位置为(数组下标):"+i+" -> "+j);
66         }else{
67             System.out.println("最大子数组的位置为(数组下标):"+first+" -> "+last);
68         }
69         return max(all,max);
70     }
71     public static void main(String[] args) {
72         double a[]={1,-2,3,5,-3,2};
73         double b[]={0,-2,3,5,-1,2};
74         double c[]={-9,-2,-3,-5,-3};
75         double d[]={4,5,-9,-8,1,2,3};
76         double e[]={4,5,1,6,1,2,3};
77         System.out.println("求数组的子数组之和的最大值为:"+maxSum(a));
78         System.out.println("求数组的子数组之和的最大值为:"+maxSum(b));
79         System.out.println("求数组的子数组之和的最大值为:"+maxSum(c));
80         System.out.println("求数组的子数组之和的最大值为:"+maxSum(d));
81         System.out.println("求数组的子数组之和的最大值为:"+maxSum(e));
82 
83     }
84 
85 }

程序运行结果如下:

最大子数组的位置为(数组下标):2 -> 3
求数组的子数组之和的最大值为:8.0
最大子数组的位置为(数组下标):2 -> 5
求数组的子数组之和的最大值为:9.0
最大子数组的位置为(数组下标):1 -> 1
求数组的子数组之和的最大值为:-2.0
最大子数组的位置为(数组下标):4 -> 1
求数组的子数组之和的最大值为:15.0
最大子数组的位置为(数组下标):0 -> 6
求数组的子数组之和的最大值为:22.0

 

第2章 数字之魅——求数组的子数组之和的最大值

标签:

原文地址:http://www.cnblogs.com/gaopeng527/p/4628396.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!