歸納法求解最大連續子序列
阿新 • • 發佈:2019-02-11
問題
求最大連續子序列的問題描述如下:
給定一個實數序列 x1, x2, ... , xn(不必是正數),尋找一個(連續的)子序列 xi, xi+1, ... , xj,使得其數值之和在所有連續子序列數值之和中是最大的。
這個問題就是最大子序列問題,所求的的這個序列就叫做——最大子序列。下面通過數學歸納法來分析和解決這個問題,解決這個問題的最好目標是: 一個演算法,能夠只掃描此序列一次就得到最大子序列。
歸納分析
根據上面的問題可以直接得到一般的歸納假設:
歸納假設: 已知如何找到規模小於 n 的序列的最大子序列。
下面假定一些變數:
- 給定序列 S(n)=(x1, x2, ... , xn
- 序列 S(n) 的子序列為 S'(n) .
- 序列 S(n) 的最大子序列為 S'M(n)=(xi, xi+1, ... , xj).
- 序列 S(n) 的最大字尾子序列為 S'E(n)=(xk, xk+1, ... , xn).
現在開始用數學歸納法來證明:
- 當 n = 1 時, S(1)=x1,如果 x1<0,則 *S'M(1)=NULL;否則 *S'M(1)=x1 .
- 當 n = n-1 時,S(n-1)=(x1, x2, ... , xn-1),假設 S'M(n-1)=(xi, xi+1, ... , xj).
-
當 n = n 時,S(n)=(x1, x2, ... , xn)=( S(n-1)
- S'M(n-1)=(xi, xi+1, ... , xj) = NULL,如果 xn<0,則 *S'M(n)=NULL;否則 *S'M(n)=xn .
- S'M(n-1)=(xi, xi+1, ... , xj) && j = n-1,此時 S'M(n-1) = S'E(n-1),如果 xn > 0,S'M(n)= S'M(n-1) + xn = (xi, xi+1, ... , xj) + xn,否則 S'M(n)= S'M(n-1)=(xi, xi+1, ... , xj) .
- S'M(n-1)
-
即上述可得證:能夠求出 S(n)=(x1, x2, ... , xn) 的最大連續子序列,不過上述的證明過程中用了增強歸納假設,這個也是這個證明的關鍵:
更強的歸納假設: 已知如何找到規模小於 n 的序列的最大子序列,以及作為字尾的最大子序列。
我們知道了 S'M(n) 和 S'E(n) 這兩個序列,演算法也就明確了。我們把 xn 加入到最大字尾子序列中,如果它的和大於原來的最大子序列,則得到一個新的最大子序列(同樣也是一個字尾),否則,保留以前的最大子序列。但求解過程還沒有結束,我們還需要尋找新的最大字尾子序列,因為不能只是簡單的把 xn 加到以前的最大字尾中,有可能以 xn 結束的最大字尾的和是負數,在這種情況下,我們就需要把NULL(空集)作為最大字尾(以及把隨後的 xn+1 也考慮進去)。
具體演算法實現
根據上面的分析過程,下面貼上具體的C++程式碼:
int Maximum_Consecutive_Subsequence(int *x, int n)
{
int global_Max = 0; // 最大子序列的和
int suffix_Max = 0; // 最大字尾子序列的和,每次迭代都會更新
int i = 0;
for (i = 0; i < n; i++)
{
if (x[i] + suffix_Max > global_Max)
{
suffix_Max = suffix_Max + x[i];
global_Max = suffix_Max;
}
else if (x[i] + suffix_Max > 0)
{
suffix_Max = suffix_Max + x[i];
}
else
{
suffix_Max = 0;
}
}
return global_Max;
}
更詳細的程式碼可以戳這裡.
2014.09.07