//线性序列的最大子段和的三种解法
1. 蛮力法
int MaxSubSum1(int* arr, int n, int& iPos, int& jPos)
{
int sum = 0;
// i和j是子串的起始位置。
for (int i = 0; i < n; ++i)
for (int j = i; j < n; ++j)
{
int thisSum = 0;
// 计算当前子串的长度。
for (int k = i; k <=j; ++k)
thisSum += arr[k];
// 更新目前为止最大子串的长度和最大子串的起始位置。
if (thisSum > sum)
{
sum = thisSum;
iPos = i;
jPos = j;
}
}
return sum;
}
算法的改进:
int MaxSubSum2(int* arr, int n, int& iPos, int& jPos)
{
int sum = 0;
for (int i = 0; i < n; ++i)
{
int thisSum = 0;
for (int j = i; j < n; ++j)
{
// 这样thisSum就能重复利用已经加起来的值,而不是每次都从零开始。
thisSum += arr[j];
if (thisSum > sum)
{
sum = thisSum;
iPos = i;
jPos = j;
}
}
}
return sum;
}
2. 分治法:
int MaxSubSum3(int* arr, int left, int right)
{
int sum = 0;
// Small(P)
if (left == right)
sum = arr[left] > 0 ? arr[left] : 0;
// If P is not small, divide P into subproblems.
else
{
// Find where to split the set.
int center = (left + right ) / 2;
// Solve the subproblems (1) and (2) recursively.
int leftSum = MaxSubSum3(arr, left, center);
int rightSum = MaxSubSum3(arr, center+1, right);
// Solve the subproblem (3)
int s1 = 0, lefts = 0;
for (int i = center; i >= left; --i)
{
lefts += arr[i];
if (lefts > s1)
s1 = lefts;
}
int s2 = 0, rights = 0;
for (int i = center + 1; i <= right; ++i)
{
rights += arr[i];
if (rights > s2)
s2 = rights;
}
// Combine the solutions of the subproblems.
sum = s1 + s2;
if (sum < leftSum)
sum = leftSum;
if (sum < rightSum)
sum = rightSum;
}
return sum;
}
3. 动态规划法:
int MaxSubSum4(int* arr, int n, int& beg, int& end)
{
int sum = 0, thisSum = 0, j = 0;
for (int i = 0; i < n; ++i)
{
// 根据动态规划式决定取舍。
if (thisSum >= 0)
thisSum += arr[i];
else
{
this
Sum = arr[i];
j = i;
}
if (thisSum > sum)
{
sum = thisSum;
end = i;
beg = j;
}
}
return sum;
}