zoukankan      html  css  js  c++  java
  • 最大连续子段和

    最大连续子段和

    •          给定长度为n的整数序列,a[1...n], 求[1,n]某个子区间[i,j]使得a[i]+…+a[j]和最大,或者求出最大的这个和。例如(-2,11,-4,13,-5,2)的最大子段和为20,所求子区间为[2,4]。

     

    •       穷举法(3次for循环)

               第1次for循环,遍历数组所有数字,即确定子段和的首个数字;

              第2次for循环,遍历数个数字之后的所有数字,即确定字段和的最后一个数字;

              第3次for循环,遍历首个数字与最后一个数字,对之间所有数字求和。

     1 int maxSum(int a[], int num, int &start, int &end){
     2     int localSum= MINNUM;
     3     for (int i = 0; i < num; i++){
     4         for (int j = i; j < num; j++){
     5             int thisSum = 0;
     6             for (int k = i; k <= j; k++){
     7                 thisSum += a[k];
     8             }
     9             if (thisSum > localSum){
    10                 start = i;
    11                 end = j;
    12                 localSum = thisSum;
    13             }
    14         }
    15     }
    16     return localSum;        
    17 }

    •       穷举优化法(2次for循环)

               第1次for循环,遍历数组所有数字,即确定子段和的首个数字;

              第2次for循环,遍历数个数字之后的所有数字,即确定字段和的最后一个数字;

              用thisSum记录不同结尾数字对应的子段和,进而比较获得对应首个数字的最大子段和

     1 int maxSum(int a[], int num, int* start, int* end){
     2     int localSum= 0;
     3     for (int i = 0; i < num; i++){
     4         int thisSum = 0;
     5         for (int k = i; k < num; k++){
     6             thisSum += a[k];
     7             if (thisSum > localSum){
     8                 *start = i;
     9                 *end = k;
    10                 localSum = thisSum;
    11             }
    12         }
    13     }
    14     return localSum;        
    15 }

    •       分治策略

               将初始最大子段和问题分解为两个相同的子问题;

        •     分别对相同的子段求解最大子段和;

        •     合并子问题的解,获得原问题的解。

                 最大子段和位于左子段

                 最大子段和位于右子段

                 最大子段和的首数字位于左子段,尾数字位于右子段

     1 int maxSum(int a[], int left, int right){
     2     int localSum = 0;
     3     if (left == right) localSum = (a[left] > 0 ? a[left] : 0); 
     4     else{
     5         int mid = (left + right)/2;
     6         int leftSum = maxSum(a, left, mid);
     7         int rightSum = maxSum(a, mid + 1, right);
     8         int sum1 = 0;     int lefts = 0;
     9         for (int i = mid; i >= left; i--){
    10             lefts += a[i];
    11             if (lefts > sum1)   sum1 = lefts;    
    12         }
    13         int sum2 = 0;  int rights = 0;
    14         for (int i = mid + 1; i <= right; i++){
    15             rights += a[i];
    16             if (rights > sum2)  sum2 = rights;
    17         }
    18         localSum = sum1 + sum2;
    19         if (localSum < leftSum) localSum = leftSum;
    20         if (localSum < rightSum) localSum = rightSum;
    21     }            return localSum;                 
    22 }

           动态规划

             令b[j]表示以位置 j 为终点的所有子区间中和最大的一个

        子问题:如j为终点的最大子区间包含了位置j-1,则以j-1为终点的最大子区间必然包括在其中

            如果b[j-1] >0, 那么显然b[j] = b[j-1] + a[j],用之前最大的一个加上a[j]即可,因为a[j]必须包含

            如果b[j-1]<=0,那么b[j] = a[j] ,因为既然最大,前面的负数必然不能使你更大

     1 int maxSum(int a[], int num)
     2 {
     3     int localSum = 0;
     4     int b = 0;
     5     for (int i = 0; i < num; i++)
     6     {
     7         if (b > 0)
     8             b += a[i];
     9         else 
    10             b = a[i];
    11         if (b > localSum)
    12              localSum = b;
    13     }
    14     return localSum;        
    15 }

       算法效率分析

             穷举法       O(n3)

            穷举优化法   O(n2)

            分治法       O(nlogn)

            动态规划法   O(n)

      附带一些完整代码:

     1 //动态规划
     2 # include<stdio.h>
     3 # include<stdio.h>
     4 int maxsum(int a[],int num)
     5 {
     6     int localsum=a[0];
     7     int b=0;
     8     for(int i=0;i<num;i++)
     9     {
    10         if(b>0)
    11             b += a[i];
    12         else
    13             b=a[i];
    14         if(b>localsum)
    15             localsum=b;
    16     }
    17     return localsum;
    18 }
    19 int main()
    20 {
    21     int a[15];
    22     int n,i;
    23     while(scanf("%d",&n)!=EOF){
    24         for(i=0;i<n;i++)
    25             scanf("%d",&a[i]);        
    26         printf("%d
    ",maxsum(a,n));
    27     }
    28     return 0;
    29 }
    30 //分治算法
    31 # include<stdio.h>
    32 int maxsum(int a[],int left,int right)
    33 {
    34     int localsum=0,i;
    35     if(left==right) 
    36         localsum=(a[left]>0)?a[left]:0;
    37     else{
    38         int mid=(left+right)/2;
    39         int leftsum=maxsum(a,left,mid);
    40         int rightsum=maxsum(a,mid+1,right);
    41         int sum1=0; int lefts=0;
    42         for(i=mid;i>=left;i--){
    43             lefts+=a[i];
    44             if(lefts>sum1) sum1=lefts;
    45         }
    46         int sum2=0; int rights=0;
    47         for(i=mid+1;i<=right;i++){
    48             rights+=a[i];
    49             if(rights>sum2) sum2=rights;
    50         }
    51         localsum=sum1+sum2;
    52         if(localsum<leftsum) localsum=leftsum;
    53         if(localsum<rightsum) localsum=rightsum;
    54     }
    55     return localsum;
    56 }
    57 int main()
    58 {
    59     int a[15];
    60     int n,temp,i,j,k,max;
    61     while(scanf("%d",&n)!=EOF){
    62         for(i=0;i<n;i++)
    63             scanf("%d",&a[i]);
    64         printf("%d
    ",maxsum(a,0,n-1));
    65     }
    66     return 0;
    67 }
    68 
    69 //暴力解法
    70 # include<stdio.h>
    71 int main()
    72 {
    73     int a[15];
    74     int n,temp,i,j,k,max;
    75     while(scanf("%d",&n)!=EOF){
    76         for(i=0;i<n;i++)
    77             scanf("%d",&a[i]);                
    78         max=0;
    79         for(i=0;i<n;i++)
    80         {
    81             for(j=i;j<n;j++)
    82             {
    83                 int temp=0;
    84                 for(k=i;k<=j;k++)
    85                     temp+=a[k];
    86                 if(temp>max)
    87                     max=temp;
    88             }
    89             
    90         }
    91         printf("%d
    ",max);
    92     }
    93     return 0;
    94 }
    View Code
  • 相关阅读:
    Shared Memory in Windows NT
    Layered Memory Management in Win32
    软件项目管理的75条建议
    Load pdbs when you need it
    Stray pointer 野指针
    About the Rebase and Bind operation in the production of software
    About "Serious Error: No RTTI Data"
    Realizing 4 GB of Address Space[MSDN]
    [bbk4397] 第1集 第一章 AMS介绍
    [bbk3204] 第67集 Chapter 17Monitoring and Detecting Lock Contention(00)
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3149707.html
Copyright © 2011-2022 走看看