程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 求數組子序列的最大和

求數組子序列的最大和

編輯:C++入門知識

一、問題描述
輸入一個整形數組,數組裡可以有正數或負數。數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。求所有子數組的和的最大值。要求時間復雜度為O(n)。

       例如輸入的數組為1, -2, 3, 10, -4, 7, 2, -5,和最大的子數組為3, 10, -4, 7, 2,因此輸出為該子數組的和18。

第一次遇到這道題是參加x迅的筆試。題目中給出了兩種解法,讓填空。

二、簡單解
拿到這道題,如果不考慮性能和復雜度,最簡單的方法就是窮舉。窮舉出所有的子數組,並求出他們的和,返回最大值。不過,復雜度為O(n3),不符合題目的要求(復雜度On)


[cpp] view plaincopyprint?
int max_sum(int *arr, int len){ 
    int max, sum; 
 
    for(int i = 0; i < len; i++) { 
        for(int j = i; j < len; j++) { 
            sum = 0; 
            for(int k = i; k <= j; k++) { 
                sum = sum + arr[k]; 
                if(sum > max) { 
                    max = sum; 
                } 
            } 
        } 
    } 
 
    if(max == 0) { 
        return max(arr, len); 
    } 
    return max; 

int max_sum(int *arr, int len){
 int max, sum;

 for(int i = 0; i < len; i++) {
  for(int j = i; j < len; j++) {
   sum = 0;
   for(int k = i; k <= j; k++) {
    sum = sum + arr[k];
    if(sum > max) {
     max = sum;
    }
   }
  }
 }

 if(max == 0) {
  return max(arr, len);
 }
 return max;
}

 

三、復雜度為N2的解

觀察上面的代碼,我們使用了3個for循環。其中最內側的for循環主要是控制每個字序列的長度,由於我們在計算的過程中,已經保存了當前最大字序列和,字序列的長度N對我們來說意義不大,因此完全可以撤消最內側的循環。只按每個字序列起始位置來計算最大和。這樣得到一個復雜度為N2的解。


[cpp] view plaincopyprint?
int max_sum2(int *arr, int len){ 
    int sum, max = 0; 
 
    for(int i = 0; i < len; i++) { 
        sum = 0; 
        for(int j = i; j < len; j++) { 
            sum = sum + arr[j]; 
            if(max < sum) { 
                max = sum; 
            } 
        } 
    } 
 
    if(max == 0) { 
        return max(arr, len); 
    } 
     
    return max; 

int max_sum2(int *arr, int len){
 int sum, max = 0;

 for(int i = 0; i < len; i++) {
  sum = 0;
  for(int j = i; j < len; j++) {
   sum = sum + arr[j];
   if(max < sum) {
    max = sum;
   }
  }
 }

 if(max == 0) {
  return max(arr, len);
 }
 
 return max;
}

 


四、更低復雜度的探索


至此,我們已經得到一個復雜度為N2的解法。那麼有沒有更低復雜度的算法呢?在N2的算法中,我們遍歷了從0到len-1開始的字序列,求出每種情況下得到的最大字序列和。那麼我們有沒有可能去掉這個循環呢?考慮使用動態規劃的思想,記max_sum[i]為從0到i的子序列的最大和,那麼可以得到遞推式:


[cpp] view plaincopyprint?
if max_sum[i] > 0   
then   
       if arr[i+1] > 0   
       then max_sum[i+1] = max_sum[i] + arr[i+1];   
else   
       max_sum[i+1] = max(0, arr[i+1])  

if max_sum[i] > 0 
then 
       if arr[i+1] > 0 
       then max_sum[i+1] = max_sum[i] + arr[i+1]; 
else 
       max_sum[i+1] = max(0, arr[i+1])

 


利用這種思路得到一個線性時間的解答:
[cpp] view plaincopyprint?
int max_sum3(int *arr, int len) { 
    int sum, max; 
 
    max = sum = 0; 
    for(int i = 0; i < len; i++) { 
        sum += arr[i]; 
        if(sum < 0) { 
            sum = 0; 
        } 
 
        if(sum > max){ 
            max = sum; 
        } 
    } 
 
    if(max == 0) { 
        return max(arr, len); 
    } 
    return max; 

int max_sum3(int *arr, int len) {
 int sum, max;

 max = sum = 0;
 for(int i = 0; i < len; i++) {
  sum += arr[i];
  if(sum < 0) {
   sum = 0;
  }

  if(sum > max){
   max = sum;
  }
 }

 if(max == 0) {
  return max(arr, len);
 }
 return max;
}
至此,我們得到一個時間復雜度On,空間復雜度O1的解。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved