返回最大总和的子数组

时间:2015-02-18 20:45:56

标签: arrays algorithm

在书中"编程访谈的元素",我遇到了,返回最大总和的子阵列的问题。我尝试了他们的解决方案,我认为我们不需要跟踪最小总和来获得最大总和的数组:

我写了另一个版本的maximumSumMine,我删除了minSum,它工作正常,评论中的输出

跟踪minSum的目的是什么,我们真的需要吗?

#include <stdio.h>
#include <limits.h>

typedef struct range {
    int start;
    int end;
    int maxSum;
} range;

void print(int *a, int start, int end) {
    for (int i = start; i <= end; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
}

// Book's code as it is
range maximumSum(int *a, int n) {
    range r;
    r.start = 0; r.end = 0;
    int minSum = 0, sum = 0, minIndex = -1, maxSum = INT_MIN;
    for (int i = 0; i < n; i++) {
        sum += a[i];
        if (sum < minSum) {
            minSum = sum;
            minIndex  = i;
        }
        if (sum - minSum > maxSum) {
            maxSum = sum - minSum;
            r.start = minIndex + 1;
            r.end = i + 1;
        }
    }
    return r;
}

range maximumSumMine(int *a, int n) {
    range r;
    r.start = 0; r.end = 0;
    int sum = 0, minIndex = -1, maxSum = INT_MIN;
    for (int i = 0; i < n; i++) {
        sum += a[i];
        if (sum < 0) {
            sum = 0;
            minIndex = i + 1;
        }
        if (sum > maxSum) {
            maxSum = sum;
            r.start = minIndex;
            r.end = i;
        }
    }
    return r;
}

void unitTests() {
    // Example 1
    int a[5] = {-2, 5, 1, -1, 4};
    range r = maximumSum(a, 5);
    print(a, r.start, r.end); // output 5 1 -1 4 0

    // Example 2
    int b[5] = {2, -5, 5, -1, 3};
    r = maximumSum(b, 5);
    print(b, r.start, r.end); // 5 -1 3 1

    // Example 1
    r = maximumSumMine(a, 5);
    print(a, r.start, r.end); // output 5 1 -1 4

    // Example 2
    r = maximumSum(b, 5);
    print(b, r.start, r.end); // 5 -1 3 1

}
int main() {
    unitTests();
    return 0;
}

1 个答案:

答案 0 :(得分:4)

您需要最小总和,因为算法涉及计算前缀和:

sums[i] = a[0] + a[1] + ... + a[i]

因此,对于每个i,您可以获得的结果为a[i]的最大金额为sums[i] - min(sums[j < i])

书籍代码在没有实际使用数组的情况下实现了这一点,因为您可以简单地跟踪最小值和当前前缀总和。

如果你只在你所做的条件下取最大的前缀和,它将不适用于负的最大总和:如果最大总和为负,你将始终输出0,因为你将前缀总和设置为0当它变为负面时。

有时,忽略负的最大总和可能完全没问题,有时则不然。我已经看到两个版本作为编程任务/问题。

示例:

a = {-1, -2, -3}
book output = -1
your output = 0