我试图找到具有开始和结束索引的最大连续子数组。我采用的方法是分而治之,具有O(nlogn)时间复杂度。
我已经测试了几个测试用例,并且开始和结束索引始终正常工作。但是,我发现如果数组包含奇数元素,则最大总和有时是正确的,有时是不正确的(看似随机)。但是对于偶数情况,它总是正确的。这是我的代码:
int maxSubSeq(int A[], int n, int &s, int &e)
{
// s and e stands for start and end index respectively,
// and both are passed by reference
if(n == 1){
return A[0];
}
int sum = 0;
int midIndex = n / 2;
int maxLeftIndex = midIndex - 1;
int maxRightIndex = midIndex;
int leftMaxSubSeq = A[maxLeftIndex];
int rightMaxSubSeq = A[maxRightIndex];
int left = maxSubSeq(A, midIndex, s, e);
int right = maxSubSeq(A + midIndex, n - midIndex, s, e);
for(int i = midIndex - 1; i >= 0; i--){
sum += A[i];
if(sum > leftMaxSubSeq){
leftMaxSubSeq = sum;
s = i;
}
}
sum = 0;
for(int i = midIndex; i < n; i++){
sum += A[i];
if(sum > rightMaxSubSeq){
rightMaxSubSeq = sum;
e = i;
}
}
return max(max(leftMaxSubSeq + rightMaxSubSeq, left),right);
}
以下是我正在使用的两个测试用例,一个有奇数元素,一个有偶数元素。
Array with 11 elements:
1, 3, -7, 9, 6, 3, -2, 4, -1, -9,
2,
Array with 20 elements:
1, 3, 2, -2, 4, 5, -9, -4, -8, 6,
5, 9, 7, -1, 5, -2, 6, 4, -3, -1,
编辑:以下是两种输出:
// TEST 1
Test file : T2-Data-1.txt
Array with 11 elements:
1, 3, -7, 9, 6, 3, -2, 4, -1, -9,
2,
maxSubSeq : A[3..7] = 32769 // Index is correct, but sum should be 20
Test file : T2-Data-2.txt
Array with 20 elements:
1, 3, 2, -2, 4, 5, -9, -4, -8, 6,
5, 9, 7, -1, 5, -2, 6, 4, -3, -1,
maxSubSeq : A[9..17] = 39 // correct
// TEST 2
Test file : T2-Data-1.txt
Array with 11 elements:
1, 3, -7, 9, 6, 3, -2, 4, -1, -9,
2,
maxSubSeq : A[3..7] = 20
Test file : T2-Data-2.txt
Array with 20 elements:
1, 3, 2, -2, 4, 5, -9, -4, -8, 6,
5, 9, 7, -1, 5, -2, 6, 4, -3, -1,
maxSubSeq : A[9..17] = 39
任何人都可以指出为什么会这样吗?提前谢谢!
答案 0 :(得分:1)
假设 n
是数组的正确大小(我们看到它作为参数传入,后来用于初始化midIndex
,但我们做不看到它的实际调用,所以必须假设你正确地做了),问题在于:
int midIndex = n / 2;
如果您的数组具有奇数个元素,我们可以将其表示为
n = 2k + 1
我们可以发现你的中间索引总是等于
(2k + 1)/ 2 = k +(1/2)
这意味着对于每个整数 k ,你总是会有一半的整数加到 k 。
C ++不会舍入接收浮点数的整数;它会截断。因此,当您希望 k + 0.5 舍入到 k + 1 时,实际上在截断后会得到 k 。
这意味着,例如,当您的数组大小为11时,midIndex
被定义为 5 。因此,您需要相应地调整代码。