如何理解最大子序列和的在線算法

目錄

 

(1)先給出在線算法的僞代碼

(2)疑問一:當子序列之和爲非正數時,爲何不能繼續使用該序列?

(3)疑問二:當子序列之和爲非正數時,爲何不從子序列中的任一元素開始往後掃描,而是從子序列之後的元素開始掃描?


(1)先給出在線算法的僞代碼

僅針對至少含有一個正數的序列

Solve_MaxSubSum(A, n):
    sum <- 0
    maxsum <- 0
    boundleft <- 0
    for i <- 0 to n-1 do
        sum <- sum + A[i]
        if sum <= 0 then
            sum <- 0
            boundleft <- i + 1
        else if sum > maxsum then
            maxsum <- sum
            boundright <- i

maxsum = A[boundleft] + ... + A[boundright]

接下來,用以下序列舉例說明在線算法的詳細步驟

可以看出,在線算法僅掃描一遍序列即可求得最大子序列;其高效的本質在於當子序列和爲非正數時,該序列要被棄掉而要從序列之後的元素開始往後掃描。

(2)疑問一:當子序列之和爲非正數時,爲何不能繼續使用該序列?

此問題比較簡單,反證法即可證明。假設此序列爲seqone,且作爲序列seqtwo的頭部序列。

由於seqone是seqtwo的頭部序列,seqtwo刪除seqone後不影響剩餘元素的連續性;

再由於seqone的序列和爲非正數,seqtwo刪除seqone後序列和一定不會減小,甚至可能增大;

因此對於seqtwo來說,seqone沒有保留的必要。

(3)疑問二:當子序列之和爲非正數時,爲何不從子序列中的任一元素開始往後掃描,而是從子序列之後的元素開始掃描?

要回答這個問題,我們截取算法步驟中的一部分來說明,假設算法從A[i]開始往後掃描,直到遇到A[k],序列和才小於或等於0

此時我們有以下條件:

條件(a): A[i] + ... + A[k] \leq 0

條件(b):A[i] + ... + A[s] > 0 (i\le s \le k-1)

接下來,我們不遵循在線算法的步驟(從序列之後的元素開始掃描),而是任取位於A[i]A[k]之間的某一元素開始往後掃描,假設此元素是A[j] (i<j\le k)

可以證明 A[j]爲首端且末端不超過A[k]的任一序列之和,一定小於當前最大子序列和

假設這段序列是A[j] ... A[r] (j\le r \le k),那麼A[j] + ... + A[r] < A[i] + ... + A[j] + ... + A[r]一定成立,否則A[i] + ... + A[j-1] \le 0,違反了條件(b)。

因此,A[j] + ... + A[r] < A[i] + ... + A[j] + ... + A[r] \le maxsum,證畢。

換句話解釋這個結論,即當子序列之和爲非正數時,沒有必要再從子序列中的任一元素開始往後掃描。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章