最大子序列和問題

輸入一組整數,求出這組數字子序列和中最大值。也就是隻要求出最大子序列的和,不必求出最大的那個序列。例如:{4,-3,5,-2,6,-7,1}的最大子序列和是10。


算法1,


//窮舉法,時間複雜度O(N^3)
int MaxSub(int Data[])
{
   int len = sizeof(Data)/sizeof(int);
   int MaxSum = 0;
   for (int i = 0;i <len;i++)
   {
      for (int j = i;j<len;j++)
      {
         int sum = 0;
         for (int k = i;k<j;k++)
         {
             sum += Data[k];
          }
         if (MaxSum < sum)
         {
             MaxSum = sum;
          }
       }
    }
    return MaxSum;
}

算法2

//窮舉法,時間複雜度O(N^2)
int MaxSub(int Data[])
{
    int len = sizeof(Data)/sizeof(int)
    int MaxSum = 0;
                                                                                                                                                                                                 
    for (int i = 0;i<len;i++)
    {
        int sum = 0;
        for (int j = i;j<len;j++)
        {
            sum += Data[j];
         }
         if (sum > MaxSum)
         {
             MaxSum = sum;
          }
      }
     return MaxSum;
}

算法3

採用分治算法思想,時間複雜度O(NlogN);

最大序列只可能出現在序列的左邊,右邊或者跨越左右兩邊,用遞歸的方法可以解決問題。


int Max(int a,int b,int c)
{
    int max = a;
    if (max < b){
        max = b;
    }
    if (max <c){
        max = c;
    }
    return max;
}
int MaxSub(int first,int last,int Data[])
{
    int lSum = 0;
    int rSum = 0;
    int lMaxSum = 0;
    int rMaxSum = 0;
                                                           
    int middle = (first + last)/2;
        
    if (last < first )      
         return 0;
                                                  
    if (last == first)
        return Data[first];
    int lData = MaxSub(first,middle,Data);
    int rData = MaxSub(middle+1,last,Data);
                                                                                 
    lMaxSum = Data[middle];
    for (int i = middle;i>=first;i--)
    {
        lSum += Data[i];
        if (lSum > lMaxSum){
            lMaxSum = lSum;
        }
    }
                                                                                 
    rMaxSum = Data[middle+1];
    for (int j = middle+1;j<=last;j++)
    {
        rSum += Data[j];
    if (rSum >rMaxSum)
    {
        rMaxSum = rSum;
    }
    }
    int num = Max(rData,lData,rMaxSum + lMaxSum);
    return num;
}

算法4

下面介紹一個線性的算法,這個算法是許多聰明算法的典型,時間複雜度爲O(N)。

主要思想:如果a[i]是負數那麼它不可能代表最大序列的起點,因爲任何包含a[i]的作爲起點的子序列都可以通過用a[i+1]作爲起點來改進。類似的有,任何的負的子序列不可能是最優子序列的前綴。

long maxSubSum4(int a[],int len)
{
    int maxsum, maxhere;
    maxsum = maxhere = a[0];   //初始化最大和爲a【0】
    for (int i=1; i<len; i++)
   {
        if (maxhere <= 0)
            maxhere = a[i];  //如果前面位置最大連續子序列和小於等於0,則以當前位置i結尾的最大連續子序列和爲a[i]
        else
            maxhere += a[i]; //如果前面位置最大連續子序列和大於0,則以當前位置i結尾的最大連續子序列和爲它們兩者之和
        if (maxhere > maxsum) {
            maxsum = maxhere;  //更新最大連續子序列和
        }
    }
    return maxsum;
                                                                                    
}

遍歷到a[i]時,如果a[i]前面的子序列和小於零,則將maxhere置爲a[i],因爲負的子序列和不會優化得到最大子序列。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章