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
  • 相关阅读:
    架构师是怎么炼成的?
    互联网架构
    软件质量属性之可测试性
    用百度 AI Studio完成猫狗识别
    【2021.02.22】智能家居之门窗传感器与人体传感器
    【2021.02.21】逻辑斯蒂回归、处理多维特征的输入
    【2020.02.20】树莓派3B安装home assistant全过程
    【2020.02.18】反向传播、线性回归
    【2021.02.17】线性模型、梯度下降算法
    【2021.02.16】pytorch导论
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3149707.html
Copyright © 2011-2022 走看看