求最大子数组

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

要求:

  • 输入一个整形数组,数组里有正数也有负数。
  • 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
  • 求所有子数组的和的最大值。要求时间复杂度为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 = arr[0];
 9     int subSum = arr[0];
10     start = 0;
11     end = 0;
12     s = 0;
13     e = 0;
14 
15     for(int i = 1;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 }

附上运行截图

原文地址:https://www.cnblogs.com/xiaoxt/p/5303601.html