【数据结构第一周】最大子列和问题整理

题目地址:http://www.patest.cn/contests/mooc-ds/01-1

算法一:暴力,直接计算出所有子列和,然后比较,显然复杂度炸裂,O(N^3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int MaxSubseqSum1(int A[],int N)
{
    int ThisSum;
    int MaxSum = 0;
    int i,j,k;
    for (i = 0; i < N; ++i)//i是子列左端的位置
    {
        for (j = i; j < N; ++j)//j是子列右端的位置
        {
            ThisSum = 0;//A[i]到A[j]的子列和
            for (k = i; k < j ; ++k)
            {
                ThisSum += A[k];
                if (ThisSum > MaxSum)
                {
                    MaxSum = ThisSum;
                }
            }
        }
    }
    return MaxSum;
}

  算法二:优化第三层循环,将复杂度降到O(N^2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int MaxSubseqSum2(int A[],int N)
{
    int ThisSum;
    int MaxSum = 0;
    int i,j;
    for (i = 0; i < N; ++i)//i是子列左端的位置
    {
        ThisSum = 0;//A[i]到A[j]的子列和
        for (j = i; j < N; ++j)//j是子列右端的位置
        {  
            ThisSum += A[j];//对于相同的i,不同的j,只要在j-1的基础上累加上1项即可
            if (ThisSum > MaxSum)
            {
                MaxSum = ThisSum;
            }
 
        }
    }
    return MaxSum;
}

  算法三:分而治之,把数组从中间分成两部分,然后递归地解决左右两边,最后考虑跨越边界的最大值。

复杂度的推算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int MaxSubseqSum3(int A[],int x,int y)
{
    if (y-x==1)
    {
        return A[x];
    }
    int mid = x+(y-x)/2;
    int leftSum = 0;
    int rightSum = 0;
    int leftMaxValue = A[m-1];
    int rightMaxValue = A[m];
    int i;
    int maxValue=max(MaxSubseqSum3(a,x,m),MaxSubseqSum3(a,m,y));
    for (i = mid - 1; i >= x; --i)
    {
        leftSum += A[i];
        leftMaxValue = max(leftMaxValue,leftSum);
    }
    for (i = m; i < y; ++i)
    {
        rightSum += A[i];
        rightMaxValue = max(rightMaxValue,rightSum);
    }
    return max(maxValue,leftMaxValue+rightMaxValue);
 
}

  算法四:在线处理,达到理想的复杂度了,O(N)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int MaxSubseqSum4(int A[],int N)
{
    int ThisSum,MaxSum;
    int i;
    ThisSum = MaxSum = 0;
    for (i = 0; i < N; ++i)
    {
        ThisSum += A[i];//向右累加
        if (ThisSum > MaxSum)
         {
            MaxSum = ThisSum;
         }else if (ThisSum < 0)
         {
            ThisSum = 0;
         }
 
    }
    return MaxSum;
}

  =============================================

最后AC的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <cstdio>
 
using namespace std;
 
#define MAXN 100000
int main()
{
    freopen("in.txt","r",stdin);
    int list[MAXN];
    int n,i,;
 
    int ThisSum, MaxSum;
    int head,tail;
 
 
    scanf("%d",&n);
    int start = 0,end = n-1;
     
    for (int i = 0; i < n; ++i)
    {
        scanf("%d",&list[i]);
    }  
        ThisSum = MaxSum = 0;
        for (int i = 0; i < n; ++i)
        {
            if (ThisSum >=0)
            {
               ThisSum += list[i];
               tail = i;
                
           }else
           {
            ThisSum = list[i];
            head = i;
            tail = i;
            }
            if (ThisSum > MaxSum ||(ThisSum == 0 && MaxSum == 0))
            {
                MaxSum = ThisSum;
                start = head;
                end = tail;
            }
         }
           printf("%d %d %d\n",MaxSum, list[start], list[end]);
    return 0;
}

  

posted @   Summer先生  阅读(585)  评论(4编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示