您的位置:首页 > 其它

最大连续子数组

2013-05-07 18:08 239 查看
题目:

输入一个整形数组,数组里有正数也有负数。

数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。

求所有子数组的和的最大值。要求时间复杂度为O(n)。

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,

因此输出为该子数组的和18。

解法一:最基本的轮询
思路:
找出所有的连续子数组,求和,比较。算法复杂度o(n^3)
代码:
/*
最基本的轮询
*/
int maxSubarray(int *a)
{
    int len = a.length;
    int sum;
    int max = (1 << 31);
    //两个外层循环确定子数组头和尾,然后求和
    for(int head = 0; head < len; ++head)
    {
        for(int tail = head; tail < len; ++tail)
        {
            sum = 0;
            for(int i = head; i <= tail; ++i) sum += a[i];
            if(max < sum) max = sum;
        }
    }
    return max;
}


解法二:去除多余的求和
思路:
sum[i,j] = sum[i, j-1] + sum[j]。算法复杂度o(n^2)
代码:
/*
去除中间多余的求和
简单的轮询有个明显的缺点:以第一个节点为头的子数组有a.length个;同时计算a[0] + a[1]的次数是a.length-1次;
因为
a[0]
a[0] + a[1]
a[0] + a[1] + a[2]
……
其实可以这样
a[0] = x
a[0] + a[1] = x + a[1] = y
a[0] + a[1] + a[2] = y + a[2]
……
*/
int maxSubarray(int *a)
{
    int len = a.length;
    int sum;
    int max = (1 << 31);
    //两个外层循环确定子数组头和尾,然后求和
    for(int head = 0; head < len; ++head)
    {
        sum = 0;
        for(int tail = head; tail < len; ++tail)
        {
            sum += a[tail];
            if(max < sum) max = sum;
        }
    }
    return max;
}


解法三:专家给出的最优解
思路:
这种方法的证明是个难点。
代码:

/*
统计学家提出的最优解
*/
int maxSubarray(int *a)
{
    int len = a.length;
    int sum = 0;
    int max = (1 << 31);
    for(int i = 0; i < len; ++i)
    {
        sum += a[i];
        if(max < sum) max = sum;
        if(sum < 0) sum = 0;
    }
    return max;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: