434
社区成员
发帖
与我相关
我的任务
分享伪代码:
#include <iostream>
#include <algorithm>
using namespace std;
int a[10000];
int n, temp, sum = 0;
int i;
int lrmaxsum(int l, int r)//单层循环(保证时间复杂度为O(nlogn))求横跨子段的maxsum
{
int m = (l + r) / 2;
int lmax = a[m];
int rmax = a[m + 1];
//分别以a[m]和a[m + 1]为起点求两段的max值
temp = 0;//记录数组动态求和的值
for (i = m; i >= l; i--)
{
temp += a[i];
if (lmax < temp)
lmax = temp;//记录temp的最大值
}
temp = 0;
for (i = m + 1; i <= r; i++)
{
temp += a[i];
if (rmax < temp)
rmax = temp;
}
return lmax + rmax;
}
int maxsum(int l, int r) //分治法递归求最大子段和maxsum
{
if (l == r)//只有一个数时maxsum为这个数本身
return a[l];
int m = (l + r) / 2;
//将数组分成两段,则最大子段和对应数组只会出现在以下3个位置:
//1.左段的子段
//2.右段的子段
//3.包含a[m]和a[m + 1]的横跨两段的子段
//1和2递归调用自身求maxsum,3调用新函数求maxsum
int lmax = maxsum(l, m);
int rmax = maxsum(m + 1, r);
int lrmax = lrmaxsum(l, r);
return max(lrmax, max(lmax, rmax));//取1 2 3的maxsum的最大值作为最终的maxsum
}
int main()
{
cin >> n;
for (i = 0; i < n; i++)
cin >> a[i];
sum = max(0, maxsum(0, n - 1)); //最大子段和sum取maxsum和0的最大值,所给的整数均为负数时sum为0
cout << sum;
return 0;
}
个人认为单纯的动态规划法在这里更为简单易懂,而且时间复杂度是O(n),在这里记录一下:
#include <iostream>
using namespace std;
int main()
{
int a[10000];
int n, sum = 0, temp = 0;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n; i++)
{
temp += a[i];
if(temp < a[i])
temp = a[i];
if (sum < temp)
sum = temp;
}
cout << sum;
return 0;
}
函数将问题通过m(中间)值将问题分成两段子问题,函数自身处理问题时是一个单层循环,因此有:
T(n) = 2T(n/2) + O(n)
所以算法的时间复杂度为O(nlogn)