【问题标题】:Return the sub-array of the maximum sum返回最大和的子数组
【发布时间】:2015-02-18 20:45:55
【问题描述】:

在《编程面试要素》一书中,我遇到了,返回最大和的子数组的问题。我尝试了他们的解决方案,我认为我们不需要跟踪最小和来获得最大和的数组:

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

跟踪 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;
}

【问题讨论】:

  • 你一定忘了问一个问题吧?你只提供了一个意见和一堵代码墙。
  • 更新了一个问题@austinwernli 我不明白作者为什么使用minSum
  • 为什么否定 2 我做了什么?????
  • 没什么,我只花了一分钟就删除了我的投票。对此感到抱歉

标签: arrays algorithm


【解决方案1】:

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

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

因此,对于每个i,以a[i] 结尾的最大总和是sums[i] - min(sums[j &lt; i])

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

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

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

例子:

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

【讨论】:

    猜你喜欢
    • 2017-06-08
    • 2017-11-05
    • 2021-06-09
    • 1970-01-01
    • 2021-05-14
    • 2022-11-21
    • 2018-03-30
    • 1970-01-01
    相关资源
    最近更新 更多