最大和子数组 O(n) 不是 Kadane 的

Posted

技术标签:

【中文标题】最大和子数组 O(n) 不是 Kadane 的【英文标题】:Maximum Sum Subarray O(n) not Kadane's 【发布时间】:2015-05-25 18:06:11 【问题描述】:

我正在阅读 Cormen 的“算法简介”。

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

现在我正在使用不同的测试场景对其进行测试,并且总是得到比 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

【问题讨论】:

如果你用伪代码解释你的算法会更好。 “比 Kadane 的结果更好”是什么意思? Kadane 的算法返回一个最优解——听起来你有一个错误。 这就是我要说的。虽然没有那么好。我的算法总是计算总和。当有很多负数时 - 它只是移动子数组的开始。我会在一分钟内用伪代码更新帖子 【参考方案1】:

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

    在输入 1 -2 10 3 上,它将跳过 10 并输出 3。我认为您可以通过将 i = ++j; 更改为 i = j; 来解决此问题。 如果j 超过末尾,则在两个不同的地方return,这将导致根本没有输出! (例如,如果列表末尾出现一长串负数,就会发生这种情况。)

我也不认为它会比 Kadane 的更快(或者更慢)。将两个数字相加是一种快速操作,就像将一个变量复制到另一个变量一样快,这就是您在移动子数组的开头时所做的事情。

【讨论】:

以上是关于最大和子数组 O(n) 不是 Kadane 的的主要内容,如果未能解决你的问题,请参考以下文章

如何找到[L,R]之间大小的最大和子数组

如何找到具有最小k长度和最大和的子数组?

LeetCodeLeetCode之乘积最大子数组——枚举+动态规划+Kadane算法

Kadane Algorithm

获得最大和的子矩阵?

算法问题拓展——kadane算法及其二维数组的扩展