求解最大连续子序列和问题

    科技2022-07-15  127

    求解最大连续子序列和问题

    【问题描述】给定一个有n(n>=1)个整数的序列,求出其中最大连续子序列的和。例如序列(-2,,11,-4,13,-5,-2)的最大子序列和为20,序列(-6,2,4,-7,5,3,2,-1,6,-9,10,-2)的最大子序列和为16。规定一个序列的最大连续子序列和至少是0,如果小于0,其结果为0。

    【问题求解】           最大连续子序列只可能出现在3个地方:           第一种:该子序列完全落在左半部分,即a[0...mid]中,采用递归求出其最大连续子序列和maxLeftSum           第二种:该子序列完全落在右半部分,即a[mid+1...right]中,采用递归求出其最大连续子序列和maxRightSum           第三种:该子序列跨越序列a的中部而占据左、右两部分。

    源程序如下:

    #include <iostream> #include <algorithm> using namespace std; //求解最大连续子序列和问题 long maxSubSum(int a[],int left,int right) { int i, j; long maxLeftSum, maxRightSum; long maxLeftBorderSum, leftBorderSum; long maxRightBorderSum, rightBorderSum; if (left==right) { //当子序列只有一个元素时,递归出口 if (a[left]>0) { return a[left]; //该元素大于0时返回它 } else { return 0; //该元素小于或者等于0时,返回0 } } int mid = (left + right) / 2; //求中间位置 maxLeftSum= maxSubSum(a,left,mid); //求左边的最大连续子序列之和 maxRightSum=maxSubSum(a, mid +1,right); //求右边的最大连续子序列之和 maxLeftBorderSum = 0; leftBorderSum = 0; for (i = mid; i >= left;i--) { //求出以左边加上a[mid]元素构成的序列的最大和 leftBorderSum += a[i]; if (leftBorderSum> maxLeftBorderSum) { maxLeftBorderSum = leftBorderSum; } } maxRightBorderSum = 0; rightBorderSum=0; for (j = mid+1; j <= right; j++) { //求出以左边加上a[mid]元素构成的序列的最大和 rightBorderSum += a[j]; if (rightBorderSum > maxRightBorderSum) { maxRightBorderSum = rightBorderSum; } } //返回三者之中的最大值 return max(max(maxLeftSum, maxRightSum), maxLeftBorderSum+ maxRightBorderSum); } int main() { int n = 0; cout << "请输入数组元素的个数" << endl; cin >> n; int *a = new int[n]; cout << "请输入数组的元素" << endl; for (int i = 0; i < n;i++) { cin >> a[i]; } cout << "最大连续子序列的和为:" << maxSubSum(a, 0, n - 1) << endl; system("pause"); return 0; }

    输出结果:

    请输入数组元素的个数 6 请输入数组的元素 -2 11 -4 13 -5 -2 最大连续子序列的和为:20 请按任意键继续. . .

    【算法分析】设求解序列a[0..n-1]最大连续子序列和的执行时间为T(n),第(1)(2)种情况的执行时间为T(n/2),第(3)中情况的执行时间为O(n),所以得到以下递推式:

          T(n)=1;                                 当n=1时

          T(n)=2T(n/2)+n                     当n>1时

    容易推出T(n)=O(nlog2n)

    Processed: 0.015, SQL: 8