ACM 最大子串行和

2021-08-29 18:18:49 字數 2626 閱讀 9070

感謝原作者的勞動:

最大子串行和問題,即給出乙個序列a1,a2,a3,...,an,問該序列的所有子串行中,各項相加後和最大是多少,甚至還可能要求給出該子串行的起始位置和終止位置。

演算法一:

最容易想到、直觀的演算法,就是枚舉子序列的任何乙個起點和終點位置,這樣一定可以得到正確答案,並且也能求出子串行的位置,但同時也可以確定的是這樣做的時間複雜度太高,達到了o(n^3),程式執行效率不高,一般都會超過時間限制。實現**如下:

// o(n^3)演算法

int maxsubsequencesum(int *seque, int size)

}return maxsum;

}演算法二:

演算法一使用了三層迴圈,但其實最裡面的那一層迴圈,即通過迴圈來計算某乙個子串行的和,這裡是可以避免的,可以使用累加的思想來代替迴圈求取子串行的和,即將複雜度降為o(n^2)。試想如果起點i確定,在列舉終點j的時候,由於j是逐漸增大的,所以當前的sum(i,j),不就是前面計算過的sum(i,j-1),然後再加上aj麼。實現**如下:

// o(n^2)演算法

int maxsubsequencesum(int *seque, int size)

}return maxsum;

}演算法三:

這裡介紹一種o(nlongn)的演算法,其根本思想是分治。根據分治三部曲,首先將序列不斷二分,最終和最大的子串行出現的位置不過以下三種可能:

1、完全在左半部

2、完全在右半部

3、跨越左右兩個部分

對於1、2情況,直接遞迴就可以找出正確答案;對於3情況,可以以中點為中心,向左算出包含左半部分最後乙個元素的最大子串行和,向右算出包含右半部份第乙個元素的最大子串行和,那麼答案就是它們的和。實現**如下:

// o(nlogn)演算法

int max3(int a, int b, int c)

int maxsubsequencesum(int *seque, int left, int right)

int mid = left + (right-left)/2;

// 遞迴呼叫,求左部分的最大和

int maxleftsum = maxsubsequencesum(seque, left, mid);

// 遞迴呼叫,求右部分的最大和

int maxrightsum = maxsubsequencesum(seque, mid+1, right);

// 定義左邊界子串行的和

int leftbordersum=0, maxleftbordersum=0;

for(int i=mid; i>=left; --i)

}// 定義右邊界子串行的和

int rightbordersum=0, maxrightbordersum=0;

for(int i=mid+1; i<=right; ++i)

}// 選出這三者中的最大值並返回

return max3(maxleftsum, maxrightsum, maxleftbordersum+maxrightbordersum);

}演算法四:

其實對於最大子串行和問題,還有時間複雜度僅為o(n)的演算法,此演算法基於以下分析:

如果ai是負數,那麼它不可能代表最優序列的起點,因為任何包含ai的作為起點的子串行都可以通過使用a[i+1]作為起點得到改進。類似的,任何負的子串行也不可能是最優子串行的字首(原理相同)。如果在內迴圈中檢測到從ai到aj的子串行的和是負數,那麼可以向後推進i。關鍵的結論是:我們不僅能夠把i推進到 i+1,而且實際上我們還可以把它一直推進到j+1。該演算法的乙個附帶優點是:它只對資料進行一次掃瞄,一旦ai被讀入並處理,它就不再需要被記憶,並且在任意時刻,演算法都能對它已經讀入的資料給出最大子串行和問題的正確答案,具有這種特性的演算法叫做「聯機演算法」,僅需要常量空間並以線性時間執行。實現**如下:

// o(n)演算法,但無法求出位置

int maxsubsequencesum(int *seque, int size)

return maxsum;

}演算法五:

演算法四的時間複雜度是最優的了,但是它有乙個不足,就是只能求出最大子串行的和,而不能求出其位置,因為在實現上並沒有記錄終點。這裡再討論另外一種演算法,時間複雜度同樣是o(n^2),但是同時也能求出位置資訊。其演算法實現依賴的是動態規劃的思想,設subsum[i]為以a[i]終止且包含a[i]的最大序列的和,則有:

1、如果subsum[i]<=0,那麼對於subsum[i+1]來說,它將沒影響,甚至減少subsum[i+1]的值,那麼subsum[i+1]不應該考慮加上它,而應該直接等於a[i+1]

2、否則,如果subsum[i]>0,那麼它將增加subsum[i+1]的值,所以subsum[i+1]應該等於subsum[i] + a[i+1]

所以,可以得出轉移方程:subsum[1] = a[1],subsum[i+1] = subsum[i]>0 ? subsum[i]+a[i+1] : a[i+1]。實現**如下:

// o(n)演算法

int maxsubsequencesum(int *seque, int size, int &left, int &right)

// 更新最大子串行

if(maxsum < subsum)

}return maxsum;

}

和最大子串行

問題描述 第一行輸入乙個正整數n 1 n 100001 第二行輸入n個整數a 0 a 10000 求該組整數子串行最大的和。解決這個問題應該考慮輸入n較大的情況,也就是說,輸入100000個數字判斷它的和最大子串行應當也能很快地算出來。我看過很多求解的 有三重for迴圈的,有兩重for迴圈的,也有使...

最大子串行和

最大子串行是要找出由數組成的一維陣列中和最大的連續子串行。比如的最大子串行就是 它的和是8,達到最大 而 的最大子串行是,它的和是6。找最大子串行的方法很簡單,只要前i項的和還沒有小於0那麼子串行就一直向後擴充套件,否則丟棄之前的子串行開始新的子串行,同時我們要記下各個子串行的和,最後找到和最大的子...

和最大子串行

時間限制 1 sec 記憶體限制 512 mb 提交 3 解決 3 提交 狀態 討論版 對於乙個給定的長度為n的整數序列a,它的 子串行 的定義是 a中非空的一段連續的元素 整數 你要完成的任務是,在所有可能的子串行中,找到乙個子串行,該子串行中所有元素的和是最大的 跟其他所有子串行相比 程式要求你...