求最大子数组

Posted 伟哥8882

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求最大子数组相关的知识,希望对你有一定的参考价值。

题目:整数数组中最大子数组的和

要求:

  • 输入一个整形数组,数组里有正数也有负数。
  • 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
  • 求所有子数组的和的最大值。要求时间复杂度为O(n)

之前想过两种设计思路,第一种是先找到数组中的最大数,从他开始 向左右实行数组的加减 ,可是后来发现 最大子数组中并不一定包含这一组数中的最大数,之后听完高逸凡同学的思路才理清问题所在,可是思路上陷入了僵局,最后我俩只能用最笨也最简单的最实用的方法来完成这个项目,先求出所有子数组之和,再求最大。

假设整型数组a[n],再设一个n*n整型数组arr[n][n],元素arr[i][j]表示从a[i]到a[j](包括a[j])的元素之和,数组有n个元素,那么一共有n(n+1)/2个子数组。即一个n*n矩阵去掉对角线的左下角。此时,算法的时间复杂度为O(n2)。

 

 1 #include <iostream>
 2 #include <iomanip>
 3 using namespace std;
 4 #define max_Num 100
 5 int main(int argc, char *argv[])
 6 {
 7     int arr[]={12,3,-885,4,423,-1122,115,-9,10};
 8     int max = INT_MIN;
 9     int flag_i,flag_j;
10     int arrtemp[max_Num][max_Num]={0};
11     for(int i = 0;i < (sizeof(arr)/sizeof(int)); i++)   //计算出所有子数列之和
12     {
13         for(int j=0;j < (sizeof(arr)/sizeof(int)); j++)
14         {
15             if(i <= j)    //arrtemp[i][j]指从arr[i]到arr[j]之和
16             {
17                 for(int k = i;k <= j;k++)
18                     arrtemp[i][j] += arr[k];
19             }
20         }
21     }
22 
23 
24     for(int i = 0;i < (sizeof(arr)/sizeof(int)); i++)
25     {
26         for(int j=0;j <(sizeof(arr)/sizeof(int)); j++)
27         {
28             if(i <= j){
29                 if( arrtemp[i][j] > max){
30                     max = arrtemp[i][j];
31                     flag_i = i;
32                     flag_j = j;
33                 }
34             }
35 
36         }
37     }
38 
39     cout <<"sum:"<< max <<"start:"<< flag_i <<"end:"<<flag_j <<endl;
40     return 0;
41 }

由于实力有限,在时间复杂度上,我没有什么思路,我的搭档解决了此问题。

动态规划(dynamic programming)解决

设subarr[i]表示以arr[i]结尾 的子数组的最大子段和,即:

subarr[i]=max{sum(arr[j~k])},其中0<=j<=i,j<=k<=i。

因此对于数组arr[0~n]的最大字段和为max{subarr[i]},其中0<=i<n。

在计算subarr[i]时,可以考虑以下三种情况:

  1. subarr[i] = subarr[i-1]+arr[i],当subarr[i-1]>0时,这时候的subarr[i]中包含arr[i]。
  2. subarr[i] = arr[i],当subarr[i-1]<=0,这时候以arr[i]重新作为subarr[i]的起点。
  3. subarr[i]不包含arr[i]的情况,这种情况在计算b[i]之前已经计算处结果,保存在b[0~i-1]中。最后计算max{b[i]}时会考虑到。

实现时可以用一个临时子数组和代替subarr

1 #include <iostream>
 2 using namespace std;
 3 #define max_Num 100
 4 int main(int argc, char *argv[])
 5 {
 6     int arr[]={12,3,-885,4,423,-1122,115,-9,10};
 7     int start,end,s,e;
 8     int sum = INT_MIN;
 9     int subSum =INT_MIN;
10     start = 0;
11     end = 0;
12     s = 0;
13     e = 0;
14 
15     for(int i = 0;i < (sizeof(arr)/sizeof(int));i++)
16     {
17         if(subSum > 0)
18         {
19             subSum += arr[i];
20             e = i;
21         }else{
22             subSum = arr[i];
23             s = i;
24             e = i;
25         }
26 
27         if(sum < subSum)
28         {
29             sum = subSum;
30             start = s;
31             end = e;
32         }
33     }
34     cout <<"sum:"<< sum <<"start:"<< start <<"end:"<<end <<endl;
35     return 0;
36 }

  截图如下:

技术分享

技术分享

 

以上是关于求最大子数组的主要内容,如果未能解决你的问题,请参考以下文章

环状数组求最大子数组

求一维数组最大最大子数组和

求一个二维整数数组中最大子数组的和

数组问题求二维整型数组最大联通子数组的和

求最大子数组(结对开发)

求最大子数组(结对开发)