最大子数组问题

问题描述:输入一个具有n个元素的数组x,输出该数组中任何连续子数组中的最大和(为使问题定义更加完整,规定当所有元素均为负数时,总和最大的子数组是0)。

该问题在算法导论和编程珠玑中都出现过,算法导论中给出的事采用分治策略,用递归法解决的:
  • 初始问题是要处理大小为n的数组,所以将它划分为两个大小近似相等的子数组,分别称为a和b。
  • 然后递归的找出a、b中元素总和最大的子数组,分别称为Max(a)和Max(b).

但是,这还不是最后的结果,因为最大的子数组不一定在a和b之中,还有可能是由a的最大子数组和b的最大子数组组成的,称这部分最大子数组为Max(c)。

代码如下:

int max_array(int a[], int first, int last)
{
    if(first > last)//0个元素是为0
        return 0;
    if(first == last)//1个元素时,取较大的一个
        return max(0, a[first]);
    int mid = (first + last) / 2;

    int left_max = 0, sum = 0;
    for(int i = mid; i >= 1; i--)//找到左半部分的最大子数组
    {
        sum += a[i];
        left_max = max(left_max, sum);
    }
    int right_max = 0, sum = 0;
    for(int i = mid + 1; i <= last; i++)//找到右半部分的最大子数组
    {
        sum += a[i];
        right_max = max(right_max, sum);
    }
    return 
        max(right_max+lef_tmax,max_array(a,first,mid),max_array(a, mid+1,last));
}

/*两个max()函数如下*/
int max(int a, int b)
{
    return a > b ? a : b;
}
int max(int a, int b, int c)
{
    return max(a, b) > c ? max(a, b) : c;
}
除此之外,编程珠玑中还给出了一个时间复杂度为O(n)的扫描算法(线性算法):

从数组的最左端开始扫描,一直到最右端为止,记下所遇到的最大和子数组。最大和初始化为0,前i个元素中,最大和子数组要么在前i-1个元素中(存在maxsofar),要么在结束位置i(存在maxendinghere)。
int max_array(int a[])
{
    int len = sizeof(a) / sizeof(int);
    int maxsofar = 0, maxendinghere = 0;
    for(int i = 0; i < len; i++)
    {
        maxendinghere = max(maxendinghere + a[i], 0);
        maxsofar = max(maxsofar, maxendinghere);
    }
}

在循环中的第一个赋值语句之前,maxendinghere是结束位置为i-1的最大字数组的和;赋值语句将其修改为结束位置为i的最大子数组的和。若加上a[i]后仍为正,则使maxendinghere增大a[i];若加上a[i]后为负,则将maxendinghere重置为0。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值