最大子段和问题(C/C++)

Description

给定有n个整数(可能为负整数)组成的序列a1, a2, …, an,求该序列连续的子段和的最大值。 如果该子段的所有元素和是负整数时定义其最大子段和为0。

Input

第一行有一个正整数n(n<1000),后面跟n个整数,绝对值都小于10000。直到文件结束。

Output

输出它的最大子段和。

Sample Input

6 -2 11 -4 13 -5 -2

Sample Output

20

参考链接: 最大字段和详解

  1. 穷举法
    时间复杂度: O ( n 3 ) O(n^3) O(n3)

    /*O(n^3)*/
    #include <stdio.h>
    #include <stdlib.h>
     
    int main()
    {
        int n;
        int num[1001];
        int i, j, k;
        int sum, max;
        while (~scanf("%d", &n))
        {
            for (i = 0; i < n; i++)
                scanf("%d", &num[i]);
            max = 0;
            for (i = 0; i < n; i++)
            {
                for (j = i; j < n; j++)
                {
                    sum = 0;
                    for (k = i; k <= j; k++)
                        sum += num[k];
                    if (sum > max)
                        max = sum;
                }
            }
            printf("%d\n", max);
        }
        return 0;
    }
    
  2. 穷举法

    时间复杂度: O ( n 2 ) O(n^2) O(n2)

    /*O(n^2)*/
    #include <stdio.h>
    #include <stdlib.h>
     
    int main()
    {
        int n;
        int num[1001];
        int i, j, k;
        int sum, max;
        while (~scanf("%d", &n))
        {
            for (i = 0; i < n; i++)
                scanf("%d", &num[i]);
            max = 0;
            for (i = 0; i < n; i++)
            {
                sum = 0;
                for (j = i; j < n; j++)
                {
                    sum += num[j];
                    if (sum > max)
                        max = sum;
                }
            }
            printf("%d\n", max);
        }
        return 0;
    }
    
  3. 分治法

    时间复杂度: O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

    /*O(nlogn)分治法*/
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
     // 分为左半段和右半段,还有从中间往两边的
    int maxSubSegSum(int num[], int left, int right)
    {
        int mid = (left + right) / 2;
     
        if (left == right)
            return num[left] > 0 ? num[left] : 0;
     
        int leftMaxSum = maxSubSegSum(num, left, mid);
        int rightMaxSum = maxSubSegSum(num, mid + 1, right);
     
        int sum = 0;
        int leftSum = 0;
        for (int i = mid; i >= left; i--)
        {
            sum += num[i];
            if (sum > leftSum)
                leftSum = sum;
        }
     
        sum = 0;
        int rightSum = 0;
        for (int i = mid + 1; i <= right; i++)
        {
            sum += num[i];
            if (sum > rightSum)
                rightSum = sum;
        }
     
        int retSum = leftSum + rightSum;
        if (retSum < leftMaxSum)
            retSum = leftMaxSum;
        if (retSum < rightMaxSum)
            retSum = rightMaxSum;
        return retSum;
    }
      
    int main()
    {
        int n;
        int num[1001];
     
        while (~scanf("%d", &n))
        {
            for (int i = 0; i < n; i++)
                scanf("%d", &num[i]);
            printf("%d\n", maxSubSegSum(num, 0, n - 1));
        }
        return 0;
    }
    
  4. 动态规划

    时间复杂度: O ( n ) O(n) O(n)

    /*O(n) 动态规划*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <memory.h>
     
    int main()
    {
        int n;
        int num[1001];
        int f[1001 + 1];
        int i;
        int max;
        while (~scanf("%d", &n))
        {
            for (i = 1; i <= n; i++)
                scanf("%d", &num[i]);
            max = 0;
            memset(f, 0, sizeof(f));
            for (i = 1; i <= n; i++)
            {
                if (f[i - 1] > 0)
                    f[i] = f[i - 1] + num[i];
                else
                    f[i] = num[i];
                if (f[i] > max)
                    max = f[i];
            }
            printf("%d\n", max);
        }
        return 0;
    }
    

    或者

    /*O(n) 动态规划*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <memory.h>
     
    int main()
    {
        int n;
        int num[1001];
        int b;
        int i;
        int max;
        while (~scanf("%d", &n))
        {
            for (i = 1; i <= n; i++)
                scanf("%d", &num[i]);
            max = 0;
            b = 0;
            for (i = 1; i <= n; i++)
            {
                b = b > 0 ? b + num[i] : num[i];
                max = b > max ? b : max;
            }
            printf("%d\n", max);
        }
        return 0;
    }
    
  • 6
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值