题目:
给定一整型数字a[]={a[0],...,a[n])},找出连续子串{a[x]),a[x+1],...,a[y]},使得和最大,其中,0<=x<=y<=n。
解法一,用循环来做,扫一遍,用两个变量分别记录当前子序列和、最大的序列和。
int LongestSubSum(int a[], int n)
{int curSum=0, maxSum=-MaxInt, i;
for(i=0; i<n; i++)
{
curSum += a[i];if(curSum > maxSum)
maxSum = curSum;if(curSum < 0)
curSum = 0;
}return maxSum;
}
Note:
这种情况能应付输入全部为负数的情况,算法会返回最大的负数
注意for里面的两个if不能颠倒了,否则全为负数时会返回0,这就不对了
若要求返回子序列和所在的区间
void LongestSubSum(int a[], int n, int* start, int* end, int* sum)
{int *dp = new int[n];
int *begin = new int[n];
int i;if(n>0)
{
dp[0] = a[0];
begin[0] = 0;
}
for(i=1; i<n; i++)
if(dp[i-1]+a[i]>a[i])
{
dp[i] = dp[i-1] + a[i];
begin[i] = begin[i-1];
}
else
{
dp[i] = a[i];
begin[i] = i;
}
int idxMax=0;
for(i=1; i<n; i++)
if(dp[idxMax] < dp[i])
idxMax = i;
*sum = dp[idxMax];
*start = begin[idxMax];
*end = idxMax;
}
解法二:
这是典型的dp问题,dp[i]表示以a[i]结尾的连续子串的最大和。(对比错误的:dp[i]
表示a[1..i]的最大连续子串和, 无法递推)
则递推方程为
dp[i]= dp[i-1]+a[i]
if dp[i-1]+a[i] > a[i];
a[i] else
int LongestSubSum(int a[], int n)
{
int *dp = new int[n];
int i;
dp[0] = 0;
for (i=1; i<n; i++)
if (dp[i-1]+a[i]>a[i])
dp[i] = dp[i-1] + a[i];
else
dp[i] = a[i];
int max = a[0];
for (i=1; i<n; i++)
if (max < dp[i])
max = dp[i];
return max;
}
若要求返回子序列和所在的区间
void LongestSubSum(int a[], int n, int* start, int* end, int* sum)
{
int *dp = new int[n];
int *begin = new int[n];
int i;
if(n>0)
{
dp[0] = a[0];
begin[0] = 0;
}
for(i=1; i<n; i++)
if(dp[i-1]+a[i]>a[i])
{
dp[i] = dp[i-1] + a[i];
begin[i] = begin[i-1];
}
else
{
dp[i] = a[i];
begin[i] = i;
}
int idxMax=0;
for(i=1; i<n; i++)
if(dp[idxMax] < dp[i])
idxMax = i;
*sum = dp[idxMax];
*start = begin[idxMax];
*end = idxMax;
}
求和最大的连续子串