最大子串行和

2021-08-21 16:56:28 字數 3856 閱讀 8387

給定乙個整數序列,a0, a1, a2, …… , an(項可以為負數),求其中最大的子串行和。

即輸入一組整數,求出這組數字子串行和中的最大值,只要求出最大子串行的和,不必求出最大值對應的序列。

最大子串行和:整數序列a1, a2,... an (可能有負數),求a1~an的乙個子串行ai~aj,使得ai到aj的和最大。

例如:序列:-2, 11, -4, 13, -5, 2, -5, -3, 12, -9,則最大子串行和為21。

序列:0, -3, 6, 8, -20, 21, 8, -9, 10, -1, 3, 6, 5,則最大子串行和為43。

方法一:

用三層迴圈,想要找到這個子串行,肯定是需要迴圈遍歷,有點類似於氣泡排序的感覺。

所以第一層迴圈確定起點,第二層迴圈確定終點,第三層迴圈在起點和終點之間遍歷。

時間複雜度:o(n^3)

即演算法的執行時間是以輸入長度的立方增長,當輸入長度過長,程式的執行效率將變得越來越大。

void maxsumone(int a, int n)

if (thissum > maxsum)

}} printf("第一種方式求最大子序和為:%d \n",maxsum);

}

方法二:

相當於改進第一種方法,只使用兩層迴圈,就是不用每次都重新加一遍,每次加完比較一遍。

時間複雜度:o(n^2)

演算法的執行時間是以輸入長度的平方增長。

void maxsumtwo(int a, int n)

} printf("第二種方式求最大子序和為:%d \n", maxsum);

}

方法三:

採用遞迴的思想,把序列分成左右兩個序列,分別求兩個序列的最大序列和,這個序列大最大序列的位置只有三種情況:

1、最大序列和完全在左邊部分;

2、最大序列和完全在右邊部分;

3、最大序列和跨越左右兩部分。

所以為了求出結果,可以分別求出左部分的最大序列和、右部分的最大序列和和跨越左右兩部分的最大序列和,然後進行比較,最大的即為所求。

求左半部分的最大子串行和,可把左半部分作為新的輸入序列通過該演算法遞迴求出。右半部分的最大子串行和也同理。

跨越左右兩部分的最大子串行和即為兩者相加。

時間複雜度:o(n logn)

int maxsumthree(int a, int left, int right)

//左右遞迴求出部分序列最大和

int center = (left + right) / 2;

int maxleftsum = maxsumthree(a, left, center);

int maxrightsum = maxsumthree(a, center + 1, right);

//左int maxleftbordersum = 0, leftbordersum = 0;

for (int i = center; i >= left; i--) }

//右int maxrightbordersum = 0, rightbordersum = 0;

for (int i = center + 1; i <= right; i++) }

//跨越兩邊的

int maxleftrightsum = maxleftbordersum + maxrightbordersum;

//求三個方面的最大序列

int maxsubsum = 0;

maxsubsum = maxleftsum > maxrightsum ? maxleftsum : maxrightsum;

maxsubsum = maxsubsum > maxleftrightsum ? maxsubsum : maxleftrightsum;

return maxsubsum;

}

方法四:

設序列為a,長度為n,從a(0)開始求和並記錄最大值,即開始計算a(0) , a(0)+a(1) , a(0)+a(1)+a(2)......,直到出現小於0的停止,若加到a(i)以後求和小於0,便從a(i+1)之後重新求和。

因為a(i-1)一定是大於0的,加上a(i)求和小於0,即a(i)是小於0的,之後求和的序列不必加上這個小於0的和值。

時間複雜度:o(n)

void maxsumfour(int a, int n)

printf("第四種方式求最大子序和為:%d \n", maxsum);

}

最後除錯使用的主程式為:

#include#include//時間複雜度為n**3

void maxsumone(int a, int n)

if (thissum > maxsum)

}} printf("第一種方式求最大子序和為:%d \n",maxsum);

}//時間複雜度為n**2

void maxsumtwo(int a, int n)

} printf("第二種方式求最大子序和為:%d \n", maxsum);

} //遞迴求解(n * logn)

int maxsumthree(int a, int left, int right)

//左右遞迴求出部分序列最大和

int center = (left + right) / 2;

int maxleftsum = maxsumthree(a, left, center);

int maxrightsum = maxsumthree(a, center + 1, right);

//左int maxleftbordersum = 0, leftbordersum = 0;

for (int i = center; i >= left; i--) }

//右int maxrightbordersum = 0, rightbordersum = 0;

for (int i = center + 1; i <= right; i++) }

//跨越兩邊的

int maxleftrightsum = maxleftbordersum + maxrightbordersum;

//求三個方面的最大序列

int maxsubsum = 0;

maxsubsum = maxleftsum > maxrightsum ? maxleftsum : maxrightsum;

maxsubsum = maxsubsum > maxleftrightsum ? maxsubsum : maxleftrightsum;

return maxsubsum;

}//時間複雜度為n

void maxsumfour(int a, int n)

printf("第四種方式求最大子序和為:%d \n", maxsum);

}int main()

; int n1 = sizeof(arr1) / sizeof(arr1[0]);

maxsumone(arr1,n1);

maxsumtwo(arr1,n1);

printf("第三種方式求最大子序和為:%d \n", maxsumthree(arr1, 0, n1));

maxsumfour(arr1, n1);

system("pause");

return 0;

}

其實第乙個和第二個方法是最容易想出來的,但是用來解決例子是沒有問題的,但是放到實際應用中就顯得捉襟見肘了。後面兩種方法比較難理解,但是是一種思想。

和最大子串行

問題描述 第一行輸入乙個正整數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中非空的一段連續的元素 整數 你要完成的任務是,在所有可能的子串行中,找到乙個子串行,該子串行中所有元素的和是最大的 跟其他所有子串行相比 程式要求你...