利用分治算法求解最大子段和问题C++
将序列一分为二,分别求两个序列的最大子段和,若最大子段和在两个序列之间,为第三种状况。
时间复杂度O(nlog2n)
#include <iostream>
using namespace std;
int MaxSum(int r[], int left, int right)
{
int Sum = 0, MidSum = 0, LeftSum = 0, RightSum = 0;
int mid, s1, s2, lefts, rights;
//如果序列长度为1,那么该值即为最大字段和的结果
if (left == right)
{
Sum = r[left];
}
else
{
mid = (left + right) / 2; //所划分的中点mid
//递归求解左右子序列
LeftSum = MaxSum(r, left, mid); //左子序列
RightSum = MaxSum(r, mid + 1, right);//右子序列
//求解左子序列
s1 = 0; lefts = 0;
for (int i = mid; i >= left; i--)
{
lefts += r[i];
if (lefts > s1)
{
s1 = lefts;
}
}
//求解右子序列
s2 = 0; rights = 0;
for (int j = mid + 1; j <= right; j++)
{
rights += r[j];
if (rights > s2)
{
s2 = rights;
}
}
//求和
MidSum = s1 + s2;
if (MidSum < LeftSum)
{
Sum = LeftSum;
}
else if (MidSum < RightSum)
{
Sum = RightSum;
}
else
{
Sum = MidSum;
}
}
return Sum;
}
以上是分治法在最大字段中的应用
在此问题中,分治法简化了问题求解的规模和步骤,之后在主函数中进行验证求解即可
接下来是利用python动态规划算法进行求解的代码,时间复杂度:O(n)。
n = int(input()) //输入个数
nums = list(map(int , input().split())) //输入序列
k = 0 //计算负数个数
for i in nums:
if i<0:
k=k+1
if k == len(nums): //如果全都是负数,则最大字段为0;
print(0)
else:
for i in range(1, len(nums))://遍历序列
nums[i] = max(nums[i], nums[i] + nums[i - 1]) //求解各个子段和
print(max(nums)) //求解最大子段和