计算在数组O(N)中具有最大总和的序列

时间:2015-01-06 21:59:07

标签: algorithm math time-complexity

如果我想计算具有最大总和的数组中的序列,当我有O(n)时间复杂度的限制时,我怎么能这样做?

例如:{1,2,3,4,-3}输出将为4,因为1 + 2 + 3 + 4的总和是最大总和,并且该序列中有4个数字

我知道如何使用O(N ^ 2)时间复杂度而不是O(n)帮助? :)

2 个答案:

答案 0 :(得分:2)

我认为你可以像这样迭代:

MaxSum = 0;
CurrentSum = 0;
MaxLen = 0;
CurrentLen = 0;

Index = GetFirstPositiveValue(); 
// This function returns the first Index where Array[Index] > 0
// O(n) 

while (Index < Array.Length()) {
    // general loop to parse the whole array
    while (Array[Index] > 0 && Index < Array.Length()) {
        CurrentSum += Array[Index];
        CurrentLen++;
        Index++
    }
    // We computed a sum of positive integer, we store the values 
    // if it is higher than the current max
    if (CurrentSum > MaxSum) {
        MaxSum = CurrentSum;
        MaxLen = CurrentLen;
    }
    // We reset the current values only if we get to a negative sum
    while (Array[Index] < 0 && Index < Array.Length()) {
        CurrentSum += Array[Index];
        CurrentLen++;
        Index++;
    }
    //We encountered a positive value. We check if we need to reset the current sum
    if (CurrentSum < 0) {
        CurrentSum = 0;
        CurrentLen = 0;
    }
}
// At this point, MaxLen is what you want, and we only went through 
// the array once in the while loop.

从第一个积极元素开始。如果每个元素都是负数,那么只需选择最高元素并且问题结束,这是一个1元素序列。

只要我们有正值,我们就会继续求和,所以我们有一个当前的最大值。当我们有一个负数时,我们检查当前最大值是否高于存储的最大值。如果是这样,我们用新值替换存储的最大值和序列长度。

现在,我们总结负数。当我们发现另一个积极因素时,我们必须检查一下:

如果当前总和是正数,那么我们仍然可以得到这个序列的最大总和。如果它是负数,那么我们可以抛弃当前的总和,因为最大总和不包含它:

在{1,-2,3,4}中,3 + 4大于1-2 + 3 + 4

只要我们没有通过整个阵列,我们就会重启这个过程。我们只有在产生负和的子序列时重置序列,并且只有在我们有更大的值时才存储最大值。

我认为这可以按预期工作,我们只会通过一两次数组。所以它是O(n)

我希望这是可以理解的,我无法清楚地表达自己的想法。使用{1,2,3,-4,5} / {1,2,3,-50,5} / {1,2,3,-50,4,5}等小例子执行此算法可能会有所帮助如果我不够清楚:)

答案 1 :(得分:0)

如果你知道长度为N的数组末尾的子阵列的最大总和,你可以简单地计算长度为N + 1的一个子阵列:

[..., X]       has max subsum S
[..., X, Y]    has max subsum max(0, S + Y)

因为您包含Y或者您有一个空的子数组(因为子数组位于列表的末尾)。

您可以通过从空列表中构建此子列,找到以任何位置结尾的子数组的所有最大总和:

[]             S = 0
[1]            S = 1
[1, 2]         S = 3
[1, 2, -4]     S = 0
[1, 2, -4, 5]  S = 5

然后,您只需要跟踪最大值和宽度。这是一些演示算法的Python代码。

def ranges(values):
    width = cum_sum = 0

    for value in values:
        cum_sum += value
        width += 1

        if cum_sum < 0:
            width = cum_sum = 0

        yield (cum_sum, width)

total, width = max(ranges([-2, 1, 2, 3, -8, 4, -3]))

total, width
#>>> (6, 3)