第二章實驗報告
- 2020 年 10 月 3 日
- 筆記
1.實踐題目名稱
最大子列和問題
2.問題描述
給定K個整數組成的序列{ N1, N2, …, NK },「連續子列」被定義為{ Ni, Ni+1, …, Nj },其中 1。「最大子列和」則被定義為所有連續子列元素的和中最大者。例如給定序列{ -2, 11, -4, 13, -5, -2 },其連續子列{ 11, -4, 13 }有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。
本題旨在測試各種不同的演算法在各種數據情況下的表現。各組測試數據特點如下:
- 數據1:與樣例等價,測試基本正確性;
- 數據2:102個隨機整數;
- 數據3:103個隨機整數;
- 數據4:104個隨機整數;
- 數據5:105個隨機整數;
輸入格式
輸入第1行給出正整數K (≤);第2行給出K個整數,其間以空格分隔。
輸出格式:
在一行中輸出最大子列和。如果序列中所有整數皆為負數,則輸出0。
輸入樣例:
6
-2 11 -4 13 -5 -2
輸出樣例:
20
3.演算法時間及空間複雜度分析(要有分析過程)
設演算法的複雜度為T(N),
第一步分解為兩個子問題為O(1)
第二步分別求解兩個子問題為O(N/2)*2
第三步合併子問題為O(N)
等式為:T(N)=O(1)+2T(N/2)+O(N)
得:T(N)=O(nlogn);
4.心得體會(對本次實踐收穫及疑惑進行總結)
其實是對與遞歸演算法的不熟悉和難以理解,最開始時採用了三重循環的方法寫程式碼,但看到最後一個測試點3000多ms時間的複雜度時,才了解為什麼要學習新的演算法。雖然至今還是很難理解透徹遞歸的寫法和思維。但我還是會多去模仿,多寫幾次就明白了
5.程式碼
#include <iostream>
using namespace std;
int max ( int a, int b, int c )
{
if (a>b)
{
if(b>c)
return a;
else
if(a<c)
return c;
}
else if (c<a)
return b;
}
int xing ( int a[], int left, int right )
{
int maxl, maxr;
int summaxl, summaxr;
int suml, sumr;
int mid, i;
if ( left == right )
{
if ( a[left] > 0 ) return a[left];
else return 0;
}
mid = ( left + right ) / 2; //找到中分點。
maxl = xing ( a, left, mid); //遞歸求左子列和。
maxr = xing( a, mid+1, right ); //遞歸求右子列和。
summaxl = 0;suml = 0;
for ( i = mid; i >= left; i– )
{
suml += a[i];
if ( suml > summaxl )
summaxl= suml;
}//左邊掃描結束。
summaxr = 0; sumr = 0;
for ( i = mid+1; i <= right; i++ )
{
sumr += a[i];
if ( sumr > summaxr )
summaxr = sumr;
}//右邊掃描結束。
/*返回「治」的結果*/
return max (maxl, maxr, summaxl + summaxr );
}
int main ()
{
int n,i;
cin>>n;
int a[n];
int left=0,right=n;
for (i=1;i<=n;i++)
{
cin>>a[i];
}
cout<<xing(a,left,right);
}