最大子数组问题

最大子数组问题,背景是股票买卖,也就是求一个数组的连续子数组的最大和,这个数组的元素一定是有负数的,要不然一定是所有元素之和。


用分冶法解决这个问题。


a[low,high]的任何连续子数组a[i,j]所处的位置必然满足下列三种情况:

  • 完全位于左子数组a[low, mid]
  • 完全位于右子数组a[mid + 1, high]
  • 跨越中点

最大子数组一定是这三种情况的所有子数组的和最大者


而任何跨越中点的 子数组都由两个子数组a[i, mid] 和a[mid + 1, j]组成,只要求出形如a[i, mid] 和a[mid + 1, j]的最大子数组,然后将其合并即可。


#include <iostream>
#include <stdlib.h>
#define LENGTH 16
using namespace std;

typedef struct
{
    int low;
	int high;
	int sum;	
}parm;

parm find_max_crossing_array(int number[], int low, int mid, int high)
{
	parm threeParm;
	
	int sum = 0;
	int leftsum = number[mid] - 1;
	int left;
	
	for(int i = mid; i >= low; i--)
	{
		sum += number[i];
		if(sum > leftsum)
		{
			leftsum = sum;
			left = i;
		} 
	} 
	sum = 0; 
	int rightsum = number[mid + 1] - 1;
	int right;
	for(int i = mid+1; i <= high; i++)
	{
		sum += number[i];
		if(sum > rightsum)
		{
			rightsum = sum;
			right = i;
		}
	}
	
	threeParm.low = left;
	threeParm.high = right;
	threeParm.sum = leftsum + rightsum; 
	return threeParm;
}
 
parm find_max_son_array(int number[], int low, int high)
{
	int mid;
	parm threeParmLeft;
	parm threeParmRight;
	parm threeParmCross;
	parm threeParm;
	
	//递归停止
	if(low == high)
	{
		threeParm.low = low;
		threeParm.high = high;
		threeParm.sum = number[low];
		return threeParm;
	} 
	else
	{
		mid = (low + high) /2;
		threeParmLeft = find_max_son_array(number, low, mid);
		threeParmRight = find_max_son_array(number, mid + 1, high);
		threeParmCross = find_max_crossing_array(number, low, mid, high);
		
		if(threeParmLeft.sum >  threeParmRight.sum && threeParmLeft.sum > threeParmCross.sum)
		{
			return threeParmLeft;
		}
		else if(threeParmRight.sum >  threeParmLeft.sum && threeParmRight.sum > threeParmCross.sum)
		{
			return threeParmRight;
		}
		else
		{
			return threeParmCross;
		}
	}
}

int main()
{
	int number[LENGTH] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};

	parm threeParm;
	threeParm = find_max_son_array(number,0,LENGTH - 1);
	
	cout << threeParm.low << " " << threeParm.high << " " << threeParm.sum << endl;
	
	system("PAUSE");
	return 0;
}


其他解法见 http://www.cnblogs.com/AlgrithmsRookie/p/5882379.html

       


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值