一、题目与要求
题目:返回一个整数数组中最大子数组的和。
要求:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大。
同时返回最大子数组的位置。
求所有子数组的和的最大值。要求时间复杂度为O(n)
二、设计思想
通过上次求解简单一维数组的最大子数组问题的解决,我们找到了一种实现时间复杂为O(n)的方法,采用的是二分法和递归进行的解决,后来再次检查那个程序发现时间复杂度是O(logn),这次我们考虑使用一种更有效的方法来实现O(n),我们重新审视了这道题目,要实现时间复杂度尽可能小的话就要尽可能少的遍历数组,这样我们采取一种方法只需要遍历一次数组就可以找出最大子数组(具体实现方法见代码及其注释)。关于实现数组回环,我们的方法是定义一个二倍长数组来首尾存取两次待求数组,以此解决回环。
三、源代码
1 /*====================================================================== 2 # Author: TianYongTao && ZhangYaPeng 3 # E-Mail: [email protected] 4 # Last modified: 2015-03-28 20:48 5 # Filename: Demo.cpp 6 # Description: 计算一维回环数组中的最大子数组并将其输出 7 ======================================================================*/ 8 # include <iostream> 9 using namespace std; 10 # define LENGTH 5 11 12 int MaxSubArr(int * arr,int & start,int & count) //start保存最大子数组起始点 count保存最大子数组长度 13 { 14 int max = 0; 15 int max1 = arr[0]; //max1保存的是全部为负数的数组中的最大值 16 int temp = 0; 17 bool flag=false; 18 for(int i=0;i<2*LENGTH;i++) //判断数组元素是否全部小于零 19 { 20 if(arr[i]>0) 21 { 22 flag=true; 23 } 24 if(arr[i]>=max1) 25 { 26 max1=arr[i]; 27 start = i; 28 } 29 } 30 if(!flag) 31 { 32 count=1; 33 return max1; //返回全部是负数的数组中最大的那个负数 34 } 35 start=0; 36 for(int i=0;i<2*LENGTH;i++) //数组不全小于零时遍历一遍求出最大子数组 37 { 38 temp+=arr[i]; 39 count++; 40 if(temp>max) 41 { 42 max = temp; 43 } 44 if(temp<=0) //如果在数组叠加过程中和小于0 则舍去 从该部分后面重新叠加 45 { 46 temp=0; 47 start=i+1; 48 count=0; 49 } 50 if(count==LENGTH) 51 { 52 if(arr[i]<0) 53 { 54 count--; 55 } 56 return max; 57 } 58 } 59 return max; 60 } 61 62 int main() 63 { 64 int Arr[LENGTH]; 65 int Array[2*LENGTH]; //以2倍首尾相接数组代替回环数组 66 int start=0; 67 int count=0; 68 cout<<"请输入"<<LENGTH<<"个整数(可正可负): "; 69 for(int i=0;i<LENGTH;i++) 70 { 71 cin>>Arr[i]; 72 } 73 int k=0; 74 for(int i=0;i<2*LENGTH;i++) 75 { 76 Array[i] = Arr[k++]; 77 if(k==LENGTH) 78 { 79 k=0; 80 } 81 } 82 int max = MaxSubArr(Array,start,count); 83 cout<<"最大子数组序列为:"; 84 for(int i=0;i<count;i++) 85 { 86 cout<<Array[start+i]<<" "; 87 } 88 cout<<endl; 89 cout<<"最大子数组的和为:"<<max<<endl; 90 return 0; 91 }
四、运行结果
五、结果测试
1.数组元素均为有序正数
2.数组元素为乱序正数
3.数组元素为有序负数
4.数组元素为乱序负数
5.数组元素为正负混合
六、心得体会
本次结对开发使我和队友田永涛逐渐意识到结对开发可以在一定程度上避免写代码时出现逻辑上的错误,并且结对开发时要充分表达自己的想法,这样才能寻求出一个对问题最优的解决方案,才能避免走弯路,我们的算法实现了时间复杂度O(n),难度上并不难,只是最初没有仔细分析到底该怎样去实现时间复杂度最小,只是一味的想考虑一些复杂的算法去解决这个问题,其实看似复杂的问题往往可能有巧妙地解决方法。