最大子列和

一、题目描述

http://www.patest.cn/contests/mooc-ds2015spring/01-%E5%A4%8D%E6%9D%82%E5%BA%A61

给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。


输入格式:


输入第1行给出正整数 K (<= 100000);第2行给出K个整数,其间以空格分隔。


输出格式:


在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。


输入样例:
6
-2 11 -4 13 -5 -2
输出样例:
20

 

二、思路解析

假设输入为-1,2,4,-6

提供了两种方法来解决最大自序列和的问题,func1是O(n^2)算法,func2是O(n)的算法。

func1中是用“组对数数”的办法,固定起点,依次向后加,即:[-1, -1+2, -1+2+4, -1+2+4-6], [2,2+4,2+4-6],[4-6],[6].....两层循环,所以是O(n^2)

func2中是考虑实际情况的算法。本算法是最大子序列求和问题,所有如果目前的自序列值thisValue已经是负的,则再往下加的话,多整体的结果起减小的作用。所以如果thisValue<0时,就抛弃目前起点开始的自序列,跳到下一个。这样只需要将数组遍历一遍,即可得到结果。

func3中是对01-复杂度2的解法,多了一个要求,即输出最大自序列中起止对应的数。

 

三、代码

 

[cpp] view plain copy
 
    1. #include <iostream>  
    2. #include <stdlib.h>  
    3. using namespace std;  
    4.   
    5. const int ARRAYSIZE = 100000;  
    6. int RESULT[3] = { 0 };  
    7.   
    8. int func1(int N, int *data);  
    9. int func2(int N, int *data);  
    10. void func3(int N, int *data);  
    11.   
    12. int main()  
    13. {  
    14.     int N = 0;  
    15.     int inputData[ARRAYSIZE] = { 0 };  
    16.     int result = 0;  
    17.     int start = 0;  
    18.     int end = 0;  
    19.   
    20.     //input the num of seq.  
    21.     cin >> N;  
    22.   
    23.     //input each number in the seq.  
    24.     for (int i = 0; i < N; i++)  
    25.     {  
    26.         cin >> inputData[i];  
    27.     }  
    28.   
    29.     //compute the sum.  
    30.     func3(N, inputData);  
    31.   
    32.     //output the result  
    33.     cout << RESULT[0] << " " << RESULT[1] << " " <<RESULT[2] << endl;  
    34.   
    35.     system("pause");  
    36.     return 0;  
    37.       
    38. }  
    39.   
    40. int func1(int N, int *data)  
    41. {  
    42. //  遍历出所有可能结果,保存最大值。复杂度为O(n^2)  
    43.     int thisValue = 0;  
    44.     int maxValue = 0;  
    45.     for (int start = 0; start < N; start++)  
    46.     {  
    47.         thisValue = data[start];  
    48.         for (int end = start + 1; end < N; end++)  
    49.         {  
    50.   
    51. //          从一个起点开始,挨个相加后面所有可能的自序列和。  
    52.             thisValue +=  data[end];   
    53.             if (thisValue > maxValue)  
    54.             {  
    55.                 maxValue = thisValue;  
    56.             }  
    57.         }  
    58.     }  
    59.   
    60. //  根据题目maxValue>0?选择返回值。  
    61.     if (maxValue > 0)  
    62.     {  
    63.         return maxValue;  
    64.     }  
    65.     else  
    66.     {  
    67.         return 0;  
    68.     }  
    69. }  
    70.   
    71. int func2(int N, int *data)  
    72. {  
    73. /*  只遍历一次,在遍历的过程中算出最大。复杂度为O(n)思路如下: 
    74.  *  1.从头开始遍历输入数据,挨个相加。thisValue表示目前子列的和,不断去更新maxValue 
    75.  *  2.在遍历过程中,以thisValue为判别条件。因为要求和的最大值,所以如果当前thisValue小于0,则舍弃此子列,thisValue重新归零。 
    76.  *  3.注意!不是说要舍弃为负数的数据,因为不知负数后面是什么。所以要以thisValue为条件。当第一个输入为负时,thisValue += data[0],也是负,自然舍弃。 
    77.  */  
    78.     int thisValue = 0;  
    79.     int maxValue = 0;  
    80.   
    81.     for (int i = 0; i < N; i++)  
    82.     {  
    83. //      定义thisValue计算方法:挨个相加  
    84.         thisValue += data[i];  
    85.   
    86. //      相加为负,对和最大无贡献,所以舍弃,即使thisValue为0  
    87.         if (thisValue < 0)  
    88.         {  
    89.             thisValue = 0;  
    90.         }  
    91.   
    92. //      当前子列和大于已有的最大,更新最大子列和  
    93.         if (thisValue > maxValue)  
    94.         {  
    95.             maxValue = thisValue;  
    96.         }  
    97.     }  
    98.   
    99. //  根据题目要求返回相应数值。>0返回最大子列值,<0返回0.  
    100.     if (maxValue > 0)  
    101.     {  
    102.         return maxValue;  
    103.     }  
    104.     else  
    105.     {  
    106.         return 0;  
    107.     }  
    108. }  
    109.   
    110. void func3(int N, int *data)  
    111. {  
    112. /*  也是最大子列和问题,但输出有变化。首先要输出最大子列和,其次要输出是最大子列和相对应子列的起止元素。 
    113.     思路:用func2中的O(n)算法,加一个计数器 
    114. */  
    115.     int thisValue = 0;  
    116.     int maxValue = 0;  
    117.     int start = 0;  
    118.     int count = 0;  
    119.     int end = 0;  
    120.     for (int i = 0; i < N; i++)  
    121.     {  
    122.         thisValue += data[i];  
    123.         if (thisValue <= 0)  
    124.         {  
    125.             count = 0;  
    126.             thisValue = 0;  
    127.         }  
    128.         else  
    129.         {  
    130.             count += 1;  
    131.             if (thisValue > maxValue)  
    132.             {  
    133.                 maxValue = thisValue;  
    134.                 end = i;  
    135.                 start = i - count + 1;  
    136.             }  
    137.         }  
    138. //      cout << "i:" << i << " start:" << start << " thisValue:" << thisValue << " end" << end << endl;  
    139.     }  
    140.   
    141.     if (maxValue > 0)  
    142.     {  
    143.         RESULT[0] = maxValue;  
    144.         RESULT[1] = data[start];  
    145.         RESULT[2] = data[end];  
    146.     }  
    147.     else  
    148.     {  
    149.         RESULT[0] = 0;  
    150.         RESULT[1] = data[0];  
    151.         RESULT[2] = data[N - 1];  
    152.     }  
posted @ 2016-01-24 10:21  面包包包包包包  阅读(611)  评论(0编辑  收藏  举报