//線性序列的最大子段和的三種解法
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;
}