MOOC 資料結構 最大子列和問題
阿新 • • 發佈:2019-01-26
原題:最大子列和
問題描述
“最大子列和”則被定義為所有連續子列元素的和中最大者。例如給定序列{ -2, 11, -4, 13, -5, -2 },其連續子列{ 11, -4, 13 }有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。
思路
窮舉法 : 設定子列的left和right,列舉出所有子列的情況,分別計算每個子列的和,進行比較求出最大值。
for(left=0;left<n;left++) for(right=left+1;right<n; right++) { current_sum=0; for(int i=left; i<right
窮舉法改進: 當left確定時,子列和隨著right的後移在上一次的計算結果上進行運算,所以可以在每次的begin開始時將當前子列和歸零。
for(int left=0; left<n; i++) { int current_sum=0; for(int right=left; right<n; right++){ current_sum+=sequence[right
線上處理 : (本題不考慮和為負數的情況)當子列和小於0時,它對於最大子列和沒有貢獻(即該段子列肯定不在最大子列當中),可以將當前子列和歸零,繼續後面的尋找。
for(int i=0; i<n; i++) { current_sum+=sequence[i]; if(current_sum>max_sum) max_sum=current_sum; if(current_sum<0)//關鍵點 current_sum=0; }
比較
方法 | 複雜度 |
---|---|
1 | O(n^3) |
2 | O(n^2) |
3 | O(n) |
加強版
問題分析
(1)考慮到全是負數和只有負數和0的情況:可以設定一個Max函式返回母序列的最大值。若最大值為0,則是隻有負數和0(也可能全為0)的情況,最大子序列就是母序列中的第一個0;若最大值小於0,則是全是負數的情況,按照題意最大子列和設為0,並輸出母序列的第一個值和最後一個值。
if(max<=0)
{
//全為負數
if(max<0){
max_sum=0;
begin=sequence[0];
end=sequence[n-1];}
int j=0;
//負數和0
if(max==0){
while(sequence[j]!=0){
j++;
}
max_sum=0;
begin=sequence[j];
end=sequence[j];
}
}
(2)解決輸出最大子列的頭和尾的問題: 可以在線上處理的方法上進行簡單的修改即可。由之前說的線上處理方法可知,在子列和小於等於0的時候對於最大子列和是沒有貢獻的,所以我們可以在子列和小於0的時候記錄下當前位置,則最大子列的開頭位置就是該位置的後一個位置,結尾位置可以直接在記錄最大子列和的時候同時記下。
for(int i=0; i<n; i++)
{
current_sum+=sequence[i];
if(current_sum<=0){
current_sum=0;
p=i+1;
}
if(current_sum>max_sum)
{
max_sum=current_sum;
end=sequence[i];
begin=sequence[p];
}
}
完整程式實現
1
#include<iostream>
using namespace std;
const int K=100000;
int subsequence1(int sequence[],int n){
int left,right;
int current_sum=0;
int max_sum=0;
for(left=0;left<n;left++)
for(right=left+1;right<n; right++)
{
current_sum=0;
for(int i=left; i<right; i++)
{
current_sum+=sequence[i];
if(current_sum>max_sum)
max_sum=current_sum;
}
}
return max_sum;
}
int subsequence2(int sequence[],int n){
int max_sum=0;
for(int i=0; i<n; i++){
int current_sum=0;
for(int j=i; j<n; j++){
current_sum+=sequence[j];
if(current_sum>max_sum)
max_sum=current_sum;
}
}
return max_sum;
}
int subsequence3(int sequence[],int n){
int current_sum=0;
int max_sum=0;
for(int i=0; i<n; i++)
{
current_sum+=sequence[i];
if(current_sum>max_sum)
max_sum=current_sum;
if(current_sum<0)
current_sum=0;
}
return max_sum;
}
int main(){
int sequence[K];
int N;
cin>>N;
for(int i=0; i<N; i++)
cin>>sequence[i];
cout<<subsequence2(sequence,N)<<endl;
return 0;
}
2加強版
#include<iostream>
using namespace std;
const int K=100000;
int Max(int sequence[],int n)//找出陣列中的最大值
{
int max=sequence[0];
for(int i=0;i<n;i++)
if(sequence[i]>max)
max=sequence[i];
return max;
}
int subsequence(int sequence[],int n){
int current_sum=0;
int max_sum=0;
int begin;
int end;
int p=0;
int max=Max(sequence,n);
if(max<=0)
{
//全為負數
if(max<0){
max_sum=0;
begin=sequence[0];
end=sequence[n-1];}
int j=0;
//負數和0
if(max==0){
while(sequence[j]!=0){
j++;
}
max_sum=0;
begin=sequence[j];
end=sequence[j];
}
}
for(int i=0; i<n; i++)
{
current_sum+=sequence[i];
if(current_sum<0){
current_sum=0;
p=i+1;
}
if(current_sum>max_sum)
{
max_sum=current_sum;
end=sequence[i];
begin=sequence[p];
}
}
cout<<max_sum<<" "<<begin<<" "<<end;
}
int main(){
int sequence[K];
int N;
cin>>N;
for(int i=0; i<N; i++)
cin>>sequence[i];
subsequence(sequence,N);
return 0;
}
雞湯
第一次寫部落格,希望可以堅持下去!