1. 程式人生 > 實用技巧 >聯機演算法(又叫線上處理,online algorithm)求最大子序列和的證明

聯機演算法(又叫線上處理,online algorithm)求最大子序列和的證明

C語言程式碼:

int MaxSubsequenceSum(const int A[], int N)
{
    int ThisSum, MaxSum, j;
    
    ThisSum = MaxSum = 0;
    for (j = 0; j < N; j++)
    {
        ThisSum += A[j];
        
        if (ThisSum > MaxSum)
            MaxSum = ThisSum;
        else if (ThisSum < 0)
            ThisSum = 0;
    }
    return MaxSum;
}

求證:這個演算法的正確性,即能夠求出最後的正確的最大子序列和。

證明:

我們可以取一個通常的待求最大自序列和的數列:

\(a_1,a_2,a_3...a_{p-1},a_p,a_{p+1}...a_n\)

這個數列一共有n項,我們可以先排除\(a_1\)為負數的情況,因為這回被自動地歸零處理。

然後我們設\(a_p\)為這個序列的第一個斷點,就是\(a_p\)之氣的所有項之和ThisSum都沒有因為序列和變成負數而歸零重置過,然後我們將要證的命題進行轉化-->我們知道\(a_1\)\(a_p\)這兩個數是可以排除作為新的子序列的起點的,所以,我們只需要證明:

  • \(a_2\)\(a_{p-1}\)
    (包括邊界,下同)之間不可能存在有子序列的和比從\(a1\)\(a_{p-1}\)之間按照演算法取出來的子序列和最大值要大;
  • \(a_1\)\(a_{p-1}\)之間不會存在一個數\(a_x\),使\(a_x\)\(a_p\)之間所有數之和為非負數。

下面我們就用反證法來證明這兩點的正確性:

首先,我們要明確一個前提,就是從\(a_1\)\(a_{p-1}\)之間任何一個以\(a_1\)為起點的子序列的和都是非負數。

  1. 對於第一點,我們假設存在一個符合條件的子序列,其起點為\(a_x, 1 < x < p - 1\),其所包含的所有數之和比從\(a1\)\(a_{p-1}\)
    之間按照演算法取出來的子序列和最大值要大。然後,根據我們的前提,我們知道索引x之前的一直到起點的子序列和一定是非負的,所以我們假設的那個子序列就還可以變得更大,如果加上所有前面的數的話,可是,這就與假設的序列和比從\(a1\)\(a_{p-1}\)之間按照演算法取出來的子序列和最大值要大這一條件相矛盾了,故,假設不成立。
  2. 對於第二點,我們假設在\(a_1\)\(a_{p-1}\)之間存在一個數\(a_x\),使\(a_x\)\(a_p\)之間所有數之和為非負數,那麼根據前提,我們加上\(a_x\)前面的所有的數,結果還是為非負的,可是,由於\(a_p\)是斷點,即ThisSum < 0,然而根據假設卻得出相反的結論,所以假設不成立。

由此,該待證命題的正確性得證。

感謝我的同學萬某,是他與我一起完善了這個證明的證法。