最大子段和(SDIBTOJ 2002)

 算法实验3:最大子段和

            Time Limit: 1 Sec Memory Limit: 64 MB
               Submit: 3289 Solved: 1424
               [Submit][Status][Discuss]
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
HINT

分别用普通O(n 3 )或O(n 2 )、分治O(nlogn)和动态规划O(n)实现。

Source

AC的代码

O(n^3)

//  O(n^3)
#include <stdio.h>
int main(void)
{
    int s[1010];
    int i,j,k;
    int n;
    int sum = 0;
    int max = 0;
    scanf("%d",&n);
    for(i = 0; i < n; i++)
        scanf("%d",s+i);
    for(i = 0; i < n; i++)
        for(j = i; j < n; j++){
            for(k = i,sum = 0; k <= j; k++)
                sum += s[k];
            if(sum > max)
                max = sum;
        }
    printf("%d\n",max);
    return 0;
}

O(n^2)

//  O(n^2)
#include <stdio.h>
int main(void)
{
    int s[1010];
    int i,j,k;
    int n;
    int sum = 0;
    int max = 0;
    scanf("%d",&n);
    for(i = 0; i < n; i++)
        scanf("%d",s+i);
    for(i = 0; i < n; i++){
        sum = 0;
        for(j = i; j < n; j++){
            sum += s[j];
            if(sum > max)
                max = sum;
        }
    }
    printf("%d\n",max);
    return 0;
}

O(nlogn)

//  O(nlogn)
#include <stdio.h>
int maxchs(int*,int,int);
int main(void)
{
    int s[1010];
    int i,j,k;
    int n;
    int sum = 0;
    int max = 0;
    scanf("%d",&n);
    for(i = 0; i < n; i++)
        scanf("%d",s+i);
    printf("%d\n",maxchs(s,0,n-1));
    return 0;
}
int maxchs(int *s, int left, int right)
{
    int i;
    int sum = 0;
    if(left == right)
        if(s[left] > 0)
            sum = s[left];
        else
            sum = 0;
    else{
        int mid = (left + right)/2;
        int lsum = maxchs(s, left, mid);
        int rsum = maxchs(s, mid+1, right);
        int sl = 0;
        int sr = 0;
        int suml = 0;
        int sumr = 0;
        for(i = mid; i >= left; i--){
            sl += s[i];
            if(sl > suml)
                suml = sl;
        }
        for(i = mid+1; i <= right; i++){
            sr += s[i];
            if(sr > sumr)
                sumr = sr;
        }
        sum = suml+sumr;
        if(sum < lsum)
            sum = lsum;
        if(sum < rsum)
            sum = rsum;
    }
    return sum;
}

O(n)
从前向后遍历一遍,一旦和小于等于0,则将和置位0,再向后加

//  O(n)
#include <stdio.h>
int main(void)
{
    int s[1010];
    int i,j,k;
    int n;
    int sum = 0;
    int max = 0;
    scanf("%d",&n);
    for(i = 0; i < n; i++)
        scanf("%d",s+i);
    for(i = 0; i < n; i++){
        if(sum > 0)
            sum += s[i];
        else
            sum = s[i];
        if(sum > max)
            max = sum;
    }
    printf("%d\n",max);
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值