最大总和子阵列O(n)不是Kadane的

时间:2015-03-22 19:04:35

标签: java algorithm arrays kadanes-algorithm

我正在阅读Cormen的“算法导论”。

对于Max Sum Subarray问题的线性算法,我提出了自己的解决方案。在实施之前没有检查现有的(嘉手纳)。

现在我正在使用不同的测试场景进行测试,并且总是比Kadena的测试结果更好。我不相信这样的运气,但找不到我错过的东西。你能看看它是否是一个可行的解决方案吗?

public void findMaxSubarray(Number[] numbers) {
    int maxSum = Integer.MIN_VALUE;
    int left = 0;
    int right = numbers.length - 1;

    int i = 0;
    int j = i + 1;
    int sum = numbers[i].intValue();

    while (i < numbers.length) {
        if (maxSum < sum) {
            maxSum = sum;
            left = i;
            right = j - 1;
        }
        if (j >= numbers.length)
            return;
        sum = sum + numbers[j].intValue();
        if (sum <= 0) {
            // ignoring "first" negative numbers. shift i to first non-negative
            while (numbers[j].intValue() <= 0) {
                if (maxSum < numbers[j].intValue()) {
                    maxSum = numbers[j].intValue();
                    left = j;
                    right = j;
                }
                if (++j >= numbers.length)
                    return;
            }
            i = ++j;
            sum = 0;
        }
        j++;
    }
    System.out.println(String.format("Max subarray is %d, [%d; %d]", maxSum, left, right));
}

更新 代码的想法是仅跟踪一个子阵列,并添加到它的尾部数字,当数字低到该总和变为负数时 - 在尾部之后设置数组的开头。 此外,开头的负面项目也会被忽略。子阵列的负责人只是向前移动了。 每次总和似乎最大 - 更新maxSum和限制。

shift i() --to first non negative number
from j = i+1 up to N.length
  sum + N[j]
  if sum <= 0
    i = j+1
    if N[i] < 0
      shift i()
    sum = 0

1 个答案:

答案 0 :(得分:0)

我认为你的算法基本上是合理的,但它有两个我可以看到的错误:

  1. 在输入1 -2 10 3上,它会跳过10和输出3.我认为您可以通过将i = ++j;更改为i = j;来解决此问题。
  2. 如果return越过末尾,则在j的两个不同位置,这将导致根本不会产生任何输出! (如果例如在列表的末尾出现一长串负数,则会发生这种情况。)
  3. 此外,我不希望它比Kadane更快(或更慢)。将两个数字相加是一个快速操作,就像将一个变量复制到另一个变量一样快,这就是你在移动子数组的开始时所做的事情。