zoukankan      html  css  js  c++  java
  • 最大子序列

    转自 http://blog.csdn.net/luxiaoxun/article/details/7438315

    问题: 
    给定一整数序列A1, A2,... An (可能有负数),求A1~An的一个子序列Ai~Aj,使得Ai到Aj的和最大 
    例如:整数序列-2, 11, -4, 13, -5, 2, -5, -3, 12, -9的最大子序列的和为21。对于这个问题,最简单也是最容易想到的那就是穷举所有子序列的方法。利用三重循环,依次求出所有子序列的和然后取最大的那个。当然算法复杂度会达到O(n^3)。

    1. int maxSubSum1(int a[],int size )   
    2. {  
    3.     int maxSum = 0;  
    4.     for ( int i = 0; i < size; i++ )  
    5.         for ( int j = 1; j < size; j++ )   
    6.         {  
    7.              int thisSum = 0;  
    8.              for ( int k = i; k <= j; k++ )  
    9.                  thisSum += a[k];  
    10.              if ( thisSum > maxSum )  
    11.                 maxSum = thisSum;  
    12.         }  
    13.     return maxSum;  
    14. }  

    这个算法很简单,i表示子序列起始下标,j表示子序列结束下标,遍历子序列的开头和结束下标,计算子序列的和,然后判断最大子序列。很明显的看出算法复杂度是O( pow( n, 3 ) )

    显然这种方法不是最优的,下面给出一个算法复杂度为O(n)的线性算法实现,算法的来源于Programming Pearls一书。在给出线性算法之前,先来看一个对穷举算法进行优化的算法,它的算法复杂度为O(n^2)。其实这个算法只是对对穷举算法稍微做了一些修改:其实子序列的和我们并不需要每次都重新计算一遍。假设Sum(i, j)是A[i] ... A[j]的和,那么Sum(i, j+1) = Sum(i, j) + A[j+1]。利用这一个递推,我们就可以得到下面这个算法: 

    1. int max_sub(int a[],int size)  
    2. {  
    3.   int i,j,v;  
    4.     int max=a[0];  
    5.   for(i=0;i<size;i++)  
    6.   {  
    7.     v=0;  
    8.     for(j=i;j<size;j++)  
    9.     {  
    10.       v=v+a[j];         //Sum(i, j+1) = Sum(i, j) + A[j+1]  
    11.       if(v>max)  max=v;  
    12.     }  
    13.   }  
    14.   return max;  
    15. }  

    那怎样才能达到线性复杂度呢?这里运用动态规划的思想。先看一下源代码实现:

    1. int max_sub2(int a[], int size)  
    2. {  
    3.   int i,max=0,temp_sum=0;  
    4.   for(i=0;i<size;i++)  
    5.   {  
    6.       temp_sum+=a[i];  
    7.       if(temp_sum>max)  
    8.         max=temp_sum;  
    9.       else if(temp_sum<0)  
    10.         temp_sum=0;  
    11.   }  
    12.   return max;  
    13. }  

    在这一遍扫描数组当中,从左到右记录当前子序列的和temp_sum,若这个和不断增加,那么最大子序列的和max也不断增加(不断更新max)。如果往前扫描中遇到负数,那么当前子序列的和将会减小。此时temp_sum 将会小于max,当然max也就不更新。如果temp_sum降到0时,说明前面已经扫描的那一段就可以抛弃了,这时将temp_sum置为0。然后,temp_sum将从后面开始将这个子段进行分析,若有比当前max大的子段,继续更新max。这样一趟扫描结果也就出来了。 

    全部代码:

     1 #include <stdio.h>
     2 
     3 int fun1(int a[], int n_size)
     4 {
     5     int max;
     6     int temp;
     7     int i, j, k;
     8     temp = 0;
     9     max = 0;
    10     
    11     for (i=0; i<n_size; i++)
    12     {
    13         for (j=i+1; j<n_size; j++)
    14         {
    15             temp = 0;
    16             for(k=i; k<=j; k++)
    17             {
    18                 temp += a[k];
    19                 if(temp >= max)
    20                     max = temp;
    21             }
    22         }
    23     }
    24     
    25     return max;
    26 }
    27 
    28 int fun2(int a[], int n_size)
    29 {
    30     int i, j;
    31     int v, max;
    32     v = a[0];
    33     max = a[0];
    34     
    35     for (i=0; i<n_size; i++)
    36     {
    37         for (j=i+1; j<n_size; j++)
    38         {
    39             v += a[j];
    40             if (v > max)
    41                 max = v;
    42         }
    43         v = 0;
    44     }
    45     return max;
    46 }
    47 
    48 int fun3(int a[], int n_size)
    49 {
    50     int i;
    51     int max, temp;
    52     temp = 0;
    53     max = 0;
    54     
    55     for (i=0; i<n_size; i++)
    56     {
    57         temp += a[i];
    58         if (temp > max)
    59             max = temp;
    60         if(temp < 0)
    61             temp = 0;
    62     }
    63     return max;
    64 }
    65 int main()
    66 {
    67     int a[5]={6,-1,5,4,-7};
    68     printf("fun1():%d
    ", fun1(a, 5));
    69     printf("fun2():%d
    ", fun2(a, 5));
    70     printf("fun3():%d
    ", fun3(a, 5));
    71     return 0;
    72 }

    运行结果:

  • 相关阅读:
    python 全栈开发,Day75(Django与Ajax,文件上传,ajax发送json数据,基于Ajax的文件上传,SweetAlert插件)
    python 全栈开发,Day73(django多表添加,基于对象的跨表查询)
    python 全栈开发,Day72(昨日作业讲解,昨日内容回顾,Django多表创建)
    bootstrap源码里的function加上了+号
    php get set方法深入理解
    20160519
    NetStatusEvent info对象的状态或错误情况的属性
    php 代码大全
    常见HTTP状态(304,200等)
    php strtotime 和 date 日期操作
  • 原文地址:https://www.cnblogs.com/laohaozi/p/5184908.html
Copyright © 2011-2022 走看看