动态编程算法(Kadane)

时间:2017-12-28 08:50:38

标签: algorithm dynamic-programming

算法说明: 最大子阵列问题 给定n个实数A(1)... A(n)的序列,确定连续的子序列A(i)... A(j),子序列中的元素之和最大化。

算法:

int kadane(int a[], int n)
{
    int overall_sum=0;  //overall maximum subarray sum
    int new_sum=0;      //sum obtained by including the current element

    for(int i=0;i<n;i++)
    {
        //new_sum is the maximum value out of current element or the sum of current element
        //and the previous sum
        new_sum=max(a[i], new_sum+a[i]);
        cout << new_sum << " : ";
        //if the calculated value of new_sum is greater than the overall sum,
        //it replaces the overall sum value
        overall_sum=max(overall_sum, new_sum);
        cout << overall_sum << endl;
    }

    return overall_sum;

}

我知道我们正试图将问题分解为小的子问题。该想法是确定n-1子序列的最大部分和以找到n序列的最大部分和。代码看起来很清楚,因为我可以在纸上找到解决方案,但这个想法看起来很神奇。有人能提供更好的解释吗?或证明其工作原理?

2 个答案:

答案 0 :(得分:0)

要100%精确,算法实际计算的是:非空子序列的最大总和,对于非空数组(对于空数组为零) ,这有些不一致)。它对所有数字都为负的数组产生影响 - 如果我们将空序列计为有效,那么结果应为0.对于这种情况,算法产生最大的负数而不是0。

证明:

在循环开始时,new_sum始终是那些以a[i]结束(不包括)a[i-1]的序列的最大总和(因此,对于i>0,最多为0i==0的{​​{1}}。通过诱导循环执行来证明。这显然适用于i=0new_sum == 0,它是空序列的总和),并且在赋值后变为i+1,因为最大和非空序列结束于a[i](这是a[i+1]之前的最后一个元素)需要包含a[i],因此a[i]本身的最大值和a[i]以及之前的总和序列。

overall_sum只是new_sum的所有a[i]值的最大值,因此表示最大全局子序列(对于某些i,它必须以{{结尾} 1}},因此最大化所有a[i]工作。)

答案 1 :(得分:0)

您已经在代码注释中包含了解其原因的解释:

new_sum is the maximum value out of current element
or the sum of current element and the previous sum

不要将算法视为最佳总和元素i,而应将其视为从元素{{1}开始的最佳总和 }。

请注意,算法不允许i在遍历中不包含当前元素。如果new_sum单独A[i]大于A[i]添加到总结为A[i-1],则A[i]包含上一部分并且我们从刮。这可以保证从A[i]开始计算的总和达到最大值。我们可能会看到它减少但到那时我们已经根据需要更新了总体最大值。