具有开始和结束索引的最大子数组

Posted

技术标签:

【中文标题】具有开始和结束索引的最大子数组【英文标题】:Max subarray with start and end index 【发布时间】:2016-08-06 06:18:46 【问题描述】:

我正在尝试找到具有开始和结束索引的最大连续子数组。我采用的方法是分治法,时间复杂度为 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,

编辑:以下是2种输出:

// 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

谁能指出为什么会这样?提前致谢!

【问题讨论】:

你有没有用调试器单步调试过这段代码? 我刚刚尝试单步执行代码,但我仍然无法找出发生这种情况的原因.. 是的,我找到了问题所在。谢谢! 【参考方案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。因此,您需要相应地调整您的代码。

【讨论】:

我知道这个问题,但是因为你的警告,我发现了问题,并在帖子中更新了它。谢谢!

以上是关于具有开始和结束索引的最大子数组的主要内容,如果未能解决你的问题,请参考以下文章

最多具有K个元素的最大连续子数组

在子数组列表中创建并查找最大值

最大子数组和问题

数组问题之求最大子数组问题

求最大子数组(结对开发)

求最大子数组(结对开发)