递归算法求最大的子数组的和

13 篇文章 2 订阅
9 篇文章 0 订阅

题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组和18以及起始的下标2,6。 

分治策略,运行时间是nlogn

使用分治技术意味着我们要将子数组划分为两个规模尽量相等的子数组,也就是找到子数组的中央位置(比如mid),然后考虑求解两个子数组A[low..mid]和A[mid+1..high]。A[low..high]的任意连续子数组A[i..j]所处的位置必然是以下三种情况之一:

(a)完全位于子数组A[low..mid]中,因此low≤i≤j≤mid

(b)完全位于子数组A[mid+1..high]中,因此mid≤i≤j≤high

(c)跨越了中点,因此low≤i≤mid≤j≤high

所以我们需要求解这三种情况的最大子数组,然后再取最大值。A[low..mid]和A[mid+1..high]可以递归求解,剩下的就是训中跨越中点的最大子数组

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

void cross_sub(int a[],int low,int mid,int high,int &max_left,int &max_right,int &sum)
{
	int sum1=0;
	int left_sum=-65536;//假设为足够小
	int right_sum=-65536;
	for(int i=mid;i>=low;i--)
	{
		sum1=sum1+a[i];
		if (sum > left_sum)
			{
				left_sum=sum1;
				max_left=i;
			}
	}
	sum1=0;
	for(int i=mid+1;i<=high;i++)
	{
		sum1=sum1+a[i];
		if (sum1 > right_sum)
			{
				right_sum=sum1;
				max_right=i;
			}
	}
	sum=left_sum+right_sum;
}

int max_sub(int a[],int low,int high,int &max_left,int &max_right,int &sum)
{
	int left_sum=-65536;
	int right_sum=-65536;	
	if(low==high)
		{	
            max_left=low;
			max_right=low;
			sum=a[low];
		}	
	else 
	{
		int mid=(low+high)/2;
		int left_low,left_high,right_low,right_high,cross_low,cross_high;
		int left_sum,right_sum,cross_sum;
		max_sub(a,low,mid,left_low,left_high,left_sum);
		max_sub(a,mid+1,high,right_low,right_high,right_sum);
		cross_sub(a,low,mid,high,cross_low,cross_high,cross_sum);
		if(left_sum>right_sum&&left_sum>cross_sum)
			{
				sum=left_sum;
				max_left=left_low;
				max_right=left_high;
			}
		if(left_sum<right_sum&&right_sum>cross_sum)
			{
				sum=right_sum;
				max_left=right_low;
				max_right=right_high;
			}
		else
		//if(left_sum<cross_sum&&right_sum<cross_sum)
			{
				sum=cross_sum;
				max_left=cross_low;
				max_right=cross_high;
			}
	}	
}


int main()
{
	int A[16]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
	int max_left,max_right,sum;
//	形参 int a[],int low,int high,int &max_left,int &max_right,int &sum
	max_sub(A,0,15,max_left,max_right,sum);
	printf("max_left,max_right,sum is%d %d %d",max_left,max_right,sum);
	
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值