第二章實驗報告

  • 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);
}