1. 程式人生 > 實用技巧 >DevOps元素週期表——1號元素 Gitlab

DevOps元素週期表——1號元素 Gitlab

1.實踐題目名稱

最大子列和問題

2.問題描述

7-1最大子列和問題(20分)

給定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.演算法描述

本題需要利用分治法分解主問題,對於本問題,在暴力窮舉的演算法的思想上進行優化,把所求區間從中間一分為二,將問題劃分為求左區間、右區間、橫跨左右區間的最大子列和的問題。左右區間的求解利用基礎的遞迴方式完成,中間的最大子列和另外做特殊處理,最後將所求的三者進行對比得到答案,這種方式能優化時間複雜度到nlog(n),大大提高效率。

程式碼:

#include<bits/stdc++.h>
using namespace std;
int three_max(int a,int b,int c){
if(a>b&&a>c) return a;
if(b>a&&b>c) return b;
if(c>a&&c>b) return c;
}
int max_subsequence(int sum[],int left,int right){
int max_left=0,max_right=0;
int max_border_left=0,max_border_right=0;
int sum_left=0,sum_right=0;
if(left==right) return 0>sum[left]?0:sum[left];
int mid=(left+right)/2;
max_left=max_subsequence(sum,left,mid);
max_right=max_subsequence(sum,mid+1,right);
for(int i=mid;i>=left;--i){
sum_left+=sum[i];
if(sum_left>max_border_left) max_border_left=sum_left;
}
for(int i=mid+1;i<=right;++i){
sum_right+=sum[i];
if(sum_right>max_border_right) max_border_right=sum_right;
}
return three_max(max_border_left+max_border_right,max_left,max_right);
}
int main(){
int k;
cin>>k;
int sum[k];
for(int i=0;i<k;++i){
cin>>sum[i];
}
cout<<max_subsequence(sum,0,k-1);
return 0;
}

4.演算法時間複雜度分析 

設演算法的複雜度為T(N),

    第一步分解為兩個子問題為O(1)

    第二步分別求解兩個子問題為O(N/2)*2

    第三步合併子問題為O(N)

    等式為:T(N)=O(1)+2T(N/2)+O(N)

    得:T(N)=O(nlogn)

5.心得體會(對本次實踐收穫及疑惑進行總結)

    本次的題目就我看來算是一道分治法的經典例題,雖然一開始我並不能理解為什麼一定要分而治之,因為在我看來都是要遍歷一遍所有資料,但是後來我逐漸想通了這種方法能節省的時間,也深刻的認識到好演算法的重要性。