演算法競賽中的時間複雜度選擇——以最大連續和問題為例
最大連續和問題
最大連續和問題。給出一個長度為
n 的序列A1,A2,…,An ,求最大連續和。換句話說,要求找到1≤i≤j≤n ,使得Ai+Ai+1+...+Aj 儘量大。
時間複雜度為n3 的演算法
LL maxConSumN3(LL *a, LL n) {
tot = 0;
conSum = -INF;
for(LL i = 0; i < n; i++) {
for(LL j = i; j < n; j++) {
LL sum = 0;
for(LL k = i; k <= j; k++) {
sum += a[k];
tot++;
}
if(sum > conSum) {
conSum = sum;
}
}
}
return conSum;
}
時間複雜度為n2 的演算法
LL maxConSumN2(LL *a, LL n) {
tot = 0;
conSum = -INF;
for(LL i = 0; i < n; i++) {
LL sum = 0;
for (LL j = i; j < n; j++) {
sum += a[j];
tot++;
if(sum > conSum) {
conSum = sum;
}
}
}
return conSum;
}
時間複雜度為nlog2n 的演算法
// 採用分治法
// 對半劃分
// 遞迴求解左半邊和右半邊的最大連續和
// 遞迴邊界為left=right
// 求解左右連線部分的最大連續和
// 合併子問題:取三者最大值
LL division(LL *a, LL lef, LL righ) {
// 遞迴邊界
if(lef == righ) {
return a[lef];
}
LL center = lef + (righ - lef) / 2;
// 左半邊最大連續和
LL maxLeftSum = division(a, lef, center);
// 右半邊最大連續和
LL maxRightSum = division(a, center + 1, righ);
// 左連線部分最大和
LL maxLeftConSum = -INF;
LL leftConSum = 0;
for(LL i = center; i >= lef; i--) {
leftConSum += a[i];
tot++;
if(leftConSum > maxLeftConSum) {
maxLeftConSum = leftConSum;
}
}
// 右連線部分最大和
LL maxRightConSum = -INF;
LL rightConSum = 0;
for(LL i = center + 1; i <= righ; i++) {
rightConSum += a[i];
tot++;
if(rightConSum > maxRightConSum) {
maxRightConSum = rightConSum;
}
}
return max(max(maxLeftSum, maxRightSum), maxLeftConSum + maxRightConSum);
}
LL maxConSumNLogN(LL *a, LL n) {
return division(a, 0, n - 1);
}
時間複雜度為n 的演算法
LL maxConSumN(LL *a, LL n) {
conSum = -INF;
LL sum = 0;
tot = 0;
for(int i = 0; i < n; i++) {
sum += a[i];
tot++;
if(sum < 0) {
sum = 0;
}
if(sum > conSum) {
conSum = sum;
}
}
return conSum;
}
測試主程式
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL INF = 100000000;
// 總執行次數
LL tot;
// 最大連續和
LL conSum;
// 求最大連續和問題
// n^3的演算法
LL maxConSumN3(LL *a, LL n) {
tot = 0;
conSum = -INF;
for(LL i = 0; i < n; i++) {
for(LL j = i; j < n; j++) {
LL sum = 0;
for(LL k = i; k <= j; k++) {
sum += a[k];
tot++;
}
if(sum > conSum) {
conSum = sum;
}
}
}
return conSum;
}
// n^2的演算法
LL maxConSumN2(LL *a, LL n) {
tot = 0;
conSum = -INF;
for(LL i = 0; i < n; i++) {
LL sum = 0;
for(LL j = i; j < n; j++) {
sum += a[j];
tot++;
if(sum > conSum) {
conSum = sum;
}
}
}
return conSum;
}
// nlogn的演算法
// 採用分治法
// 對半劃分
// 遞迴求解左半邊和右半邊的最大連續和
// 遞迴邊界為left=right
// 求解左右連線部分的最大連續和
// 合併子問題:取三者最大值
LL division(LL *a, LL lef, LL righ) {
// 遞迴邊界
if(lef == righ) {
return a[lef];
}
LL center = lef + (righ - lef) / 2;
// 左半邊最大連續和
LL maxLeftSum = division(a, lef, center);
// 右半邊最大連續和
LL maxRightSum = division(a, center + 1, righ);
// 左連線部分最大和
LL maxLeftConSum = -INF;
LL leftConSum = 0;
for(LL i = center; i >= lef; i--) {
leftConSum += a[i];
tot++;
if(leftConSum > maxLeftConSum) {
maxLeftConSum = leftConSum;
}
}
// 右連線部分最大和
LL maxRightConSum = -INF;
LL rightConSum = 0;
for(LL i = center + 1; i <= righ; i++) {
rightConSum += a[i];
tot++;
if(rightConSum > maxRightConSum) {
maxRightConSum = rightConSum;
}
}
return max(max(maxLeftSum, maxRightSum), maxLeftConSum + maxRightConSum);
}
LL maxConSumNLogN(LL *a, LL n) {
return division(a, 0, n - 1);
}
// n的演算法
LL maxConSumN(LL *a, LL n) {
conSum = -INF;
LL sum = 0;
tot = 0;
for(int i = 0; i < n; i++) {
sum += a[i];
tot++;
if(sum < 0) {
sum = 0;
}
if(sum > conSum) {
conSum = sum;
}
}
return conSum;
}
int main() {
LL a[] = {-2, 3, 4, 5, -6, 7, -1, 2, 6};
cout << "時間複雜度為N^3的演算法:" << maxConSumN3(a, 9);
cout << "\t 計算次數為:" << tot << endl;
cout << "時間複雜度為N^2的演算法:" << maxConSumN2(a, 9);
cout << "\t 計算次數為:" << tot << endl;
tot = 0;
cout << "時間複雜度為NLogN的演算法:" << maxConSumNLogN(a, 9);
cout << "\t 計算次數為:" << tot << endl;
cout << "時間複雜度為N的演算法:" << maxConSumN(a, 9);
cout << "\t\t 計算次數為:" << tot << endl;
return 0;
}
輸出結果為
時間複雜度為N^3的演算法:20 計算次數為:165
時間複雜度為N^2的演算法:20 計算次數為:45
時間複雜度為NLogN的演算法:20 計算次數為:29
時間複雜度為N的演算法:20 計算次數為:9
Process returned 0 (0x0) execution time : 0.196 s
Press any key to continue.
演算法競賽中的時間複雜度選擇
假設機器速度是每秒
運算量 | ||||||
最大規模 | ||||||
速度擴大兩倍以後 |
表還給出了機器速度擴大兩倍後,演算法所能解決規模的對比。可以看出,
不過需要注意的是,上界分析的結果在趨勢上能反映演算法的效率,但有兩個不精確性: 一是公式本身的不精確性。例如,“非主流”基本操作的影響、隱藏在大O記號後的低次項和最高項係數;二是對程式實現細節與計算機硬體的依賴性,例如,對複雜表示式的優化計算、把記憶體訪問方式設計得更加“cache友好”等。在不少情況下,演算法實際能解決的問題規模與表所示有著較大差異。
儘管如此,表還是有一定借鑑意義的。考慮到目前主流機器的執行速度,多數演算法競賽題目所選取的資料規模基本符合此表。例如,一個指明
相關推薦
演算法競賽中的時間複雜度選擇——以最大連續和問題為例
最大連續和問題 最大連續和問題。給出一個長度為n的序列 A1,A2,…,An,求最大連續和。換句話說,要求找到1≤i≤j≤n,使得Ai+Ai+1+...+Aj儘量大。 時間複雜度為n3的演算法 LL maxConSumN3(LL *a, L
以最大連續和為例的演算法分析
學習劉汝佳老師的《演算法競賽》總結 最大連續和問題 給出一個長度為n的序列A1,A2,……,An,要求找到1≤i≤j≤n,使得Ai+Ai+1+……+Aj儘量大。 一.使用列舉,程式如下: tot = 0; best = A[1]; //初始最大值
演算法中時間複雜度概括——o(1)、o(n)、o(logn)、o(nlogn)
在描述演算法複雜度時,經常用到o(1), o(n), o(logn), o(nlogn)來表示對應演算法的時間複雜度。這裡進行歸納一下它們代表的含義:這是演算法的時空複雜度的表示。不僅僅用於表示時間複雜度,也用於表示空間複雜度。 O後面的括號中有一個函式,指明某個演算法的
計數排序,傳說中時間複雜度O(n+k)的排序演算法
基本思想 假設數序列中小於元素a的個數為n,則直接把a放到第n+1個位置上。當存在幾個相同的元素時要做適當的調整,因為不能把所有的元素放到同一個位置上。計數排序假設輸入的元素都是0到k之間的整數。 回到頂部 參考程式碼 #include &
【轉】演算法中時間複雜度概括——o(1)、o(n)、o(logn)、o(nlogn)
在描述演算法複雜度時,經常用到o(1), o(n), o(logn), o(
演算法分析(時間複雜度和空間複雜度)
演算法分析(時間複雜度和空間複雜度) 對於一個給定的演算法需要做兩項分析,第一就是證明演算法的正確性,第二就是計算演算法的複雜度。演算法的複雜度包括時間複雜度和空間複雜度。 1 度量演算法效率的方法 共存在兩種方法:事後統計法和事前分析估計演算法。 事後統計法:先將演算法實現,然
初學者學演演算法|從時間複雜度認識常見演演算法(一)
O(log n):二分搜尋法時間複雜度為 O(log n) 的演演算法(這邊的 log 都是以二為底),代表當輸入的數量是 n 時,執行的步驟數會是 log n。(讓忘記 log 是什麼的同學們複習一下,當 log n = x 的意思是 n = 2^x,如果這部分的腦細胞尚未復活,且讓我們先記住 n = 2^
演算法分析之時間複雜度與空間複雜度
演算法的評價指標主要是正確性,健壯性、可讀性和有效性4個方面,有效性又包括時間複雜度和空間複雜度。 演算法的時間複雜度和空間複雜度通常採用數量級的形式來表示,而數量的形式有常量階、對數階、線性階、線性對數階、平方階、立方階、指數階、階乘階等。若演算法的時間複雜度和空間複雜度
preNoip中時間複雜度的計算
特徵方程法解一階線性代數遞推式 數列{ana_nan}滿足a1=b,an+1=can+da_1=b,a_{n+1}=ca_n+da1=b,an+1=can+d,求該數列的通項公式 針對遞推關係
KMP演算法介紹及時間複雜度分析
概念:字串中 一個字元前面的字串 的字首與字尾的最長匹配長度(短的那個字串) 注意:字首與字尾不可以是整個子字串 例如:a b c a b c d , d位置的最長匹配長度為3,abc 與 abc 匹配 Next陣列:長度與字串長度一致,每個位置儲存對應字元的最長匹配長
演算法分析神器—時間複雜度
時間複雜度是學習演算法的基石,今天我們來聊聊為什麼要引入時間複雜度,什麼是時間複雜度以及如何去算一個演算法的時間複雜度 刻畫演算法的執行時間 某日,克叫來了慧子打算給他補習補習一下基礎知識,只見克寫了一段非常簡單的程式碼 克 你說一下這段程式碼會執行多長時間
面試題:top k演算法O(n)時間複雜度
在《資料結構與演算法分析--c語言描述》一書,第7章第7.7.6節中,闡述了一種在平均情況下,時間複雜度為O(N)的快速選擇演算法。如下述文字: 選取S中一個元素作為樞紐元v,將集合S-{v}分割成S1和S2,就像快速排序那樣 如果k <= |S1|,那麼第k個最小
常用排序演算法穩定性、時間複雜度分析
1、 選擇排序、快速排序、希爾排序、堆排序不是穩定的排序演算法, 氣泡排序、插入排序、歸併排序和基數排序是穩定的排序演算法。 2、研究排序演算法的穩定性有何意義? 首先,排序演算法的穩定性大家應該都知道,通俗地講就是能保證排序前兩個相等的資
淺談直接插入排序演算法思想以及時間複雜度分析
研究意義 直接插入排序是最基本的一種排序演算法,其思想簡單,容易掌握,對後期的學習也有一定的幫助。 必備知識(之後不再敘述) 排序:將一組雜亂無章的資料排列成一個按關鍵字有序的序列。 穩定性:關鍵值相
排序演算法 (穩定性時間複雜度分析)
1、 選擇排序、快速排序、希爾排序、堆排序不是穩定的排序演算法, 氣泡排序、插入排序、歸併排序和基數排序是穩定的排序演算法。 2、研究排序演算法的穩定性有何意義? 首先,排序演算法的穩定性大家應該都知道,通俗地講就是能保證排序前兩個相等的資
BZOJ2038: [2009國家集訓隊]小Z的襪子(hose) 莫隊演算法 莫隊演算法講解及時間複雜度證明
2038: [2009國家集訓隊]小Z的襪子(hose) Time Limit: 20 Sec Memory Limit: 259 MB Submit: 7088 Solved: 3258
自己整理的幾種常見排序演算法,及時間複雜度空間複雜度。c++程式設計
/***************************************************** copyright (C), 2014-2015, Lighting Studio. Co., Ltd. File name: Author:fhb
各種排序演算法比較:時間複雜度,空間複雜度
時間複雜度 n^2表示n的平方,選擇排序有時叫做直接選擇排序或簡單選擇排序 排序方法 平均時間 最好時間 最壞時間 桶排序(不穩定) O(n) O(n) O(n) 基數排序(穩定) O(n) O(n) O(n) 歸併排序(穩定) O(nlogn) O(nlogn) O(nlogn) 快速排序(不穩定)
有1,2,....一直到n的無序陣列,求排序演算法,要求時間複雜度為O(n),空間複雜度O(1)
http://blog.csdn.net/dazhong159/article/details/7921527 1、有1,2,....一直到n的無序陣列,求排序演算法,並且要求時間複雜度為O(n),空間複雜度O(1),使用交換,而且一次只能交換兩個數。 #include &
演算法 歸併排序的複雜度分析(含圖解流程和Master公式)
圖解流程 整體流程如下: 細節流程: 第一步: 第二步: 第三步: 第四步: 第五步: 第六步: 第七步: 第八步: