7-1 最大子列和问题 (20分)
给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1。“最大子列和”则被定义为所有连续子列元素的和中最大者。
例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。
对最大子列和的分析: 我对于题目的理解是这样子的:给定一个数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),然后返回其最大和。
1 int maxWidth(int left, int right){ 2 //递归算法--每个递归内部包含三个求值操作 3 //1、中位数左边(mid)的最大序列和 4 //2、中位数右边(mid+1)的最大序列和 5 //3、相对中位数来说跨了左右的最大序列和 6 7 //每个递归结束条件的判断 8 if(left==right){ 9 return a[left]; 10 } 11 int mid = (left+right)/2; 12 int lch = maxWidth(left, mid);//计算左边的最大序列和 13 int rch = maxWidth(mid+1, right);//计算右边的序列和 14 //计算跨左右的最大子序列和 15 int lnum, rnum; 16 int ln = 0;//辅助判断 17 lnum=a[mid]; 18 //计算从 mid 开始向左累加的最大序列和 19 for(int i=mid;i>=left;i--){ 20 ln+=a[i]; 21 if(ln>lnum) lnum=ln; 22 } 23 rnum=a[mid+1]; 24 ln=0; 25 //计算从 mid+1 开始向右累加的最大序列和 26 for(int i=mid+1;i<=right;i++){ 27 ln+=a[i]; 28 if(ln> 29 rnum) rnum=ln; 30 } 31 return maxNum(rnum+lnum, lch, rch); 32 }
上面是我的核心代码,利用了递归分治的思想,每次递归进行三大步的操作,第一步在当前中心点向左搜索找出最大子序列和,第二步在当前中心点向右搜索找出最大子序列和,第三步在中心点下标分别向右和向左遍历找出最大子序列和,上述三者的最大值作为本层递归的返回值给上一层递归进行调用。
时间复杂度O(n*lg n) 这里用主定理去求解 T(n) = 2*T(n/2) + O(n)
每次将问题分解为两个子问题,每个子问题的长度为原问题的一半, O(n)包含了问题分解和子问题解合并的代价,从代码上来看,分解的过程包含了一些 O(1)的操作,然后有两个循环体,一个是从头到中间,另外一个是从中间到尾部, 所以加起来时间复杂度为 O(n), O(n) = n的 logb a次方 , log b a = 1, 因为 a=b时要成一个 lgn 所以总的时间复杂度为 O(n*lg n)
心得:有些地方要看清楚题目的描述,比如说全为负数的时候返回的是0 而不是最大的负数,之前想当然的认为是返回最大负数。