1. 程式人生 > >MOOC 資料結構 最大子列和問題

MOOC 資料結構 最大子列和問題

原題:最大子列和

問題描述

“最大子列和”則被定義為所有連續子列元素的和中最大者。例如給定序列{ -2, 11, -4, 13, -5, -2 },其連續子列{ 11, -4, 13 }有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。

思路

  1. 窮舉法 : 設定子列的left和right,列舉出所有子列的情況,分別計算每個子列的和,進行比較求出最大值。

    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; } }
  2. 窮舉法改進: 當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
    ]; if(current_sum>max_sum) max_sum=current_sum; } }
  3. 線上處理 : (本題不考慮和為負數的情況)當子列和小於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;
}

雞湯

第一次寫部落格,希望可以堅持下去!