求最大子数组
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]时,可以考虑以下三种情况:
- subarr[i] = subarr[i-1]+arr[i],当subarr[i-1]>0时,这时候的subarr[i]中包含arr[i]。
- subarr[i] = arr[i],当subarr[i-1]<=0,这时候以arr[i]重新作为subarr[i]的起点。
- 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 }
截图如下:
!--StartFragment>
以上是关于求最大子数组的主要内容,如果未能解决你的问题,请参考以下文章