最大子段和(二)

最大子段和问题

 

解法二:分治法

算法分析:

最大子段和可能在三处出现。
1)整个出现在输入数据的左半部
2)整个出现在右半部。

3)跨越输入数据的中部从而位于左右两半部分之中
前两种情况可以递归求解,第三种情况的最大和可以通过求出前半部分的最大和(包含前半部分的最后一个元素)
以及后半部分的最大和(包含后半部分的第一个元素)而得到,前后两部分和相加。
三部分中的最大者,即为最大子段和.

例如:

前半部分        后半部分

4  -3  5  -2    -1  2  6  -2

其中前半部分的最大子段和为6(A1到A3),而后半部分的最大子段和为8(A6到A7);

前半部分包含其最后一个元素的最大和为4(A1到A4),后半部分包含其第一个元素的最大和为7(A5到A7),

则横跨这两部分的最大和为4+7=11;

故该序列的最大字段和为11

 

算法实现如下:

/*
 * description: 最大子段和
 * 分治策略
 * 最大子段和可能在三处出现。
 * 1)整个出现在输入数据的左半部
 * 2)整个出现在右半部。
 * 3)跨越输入数据的中部从而位于左右两半部分之中
 * 前两种情况可以递归求解,第三种情况的最大和可以通过求出前半部分的最大和(包含前半部分的最后一个元素)
 * 以及后半部分的最大和(包含后半部分的第一个元素)而得到,前后两部分和相加。
 * 三部分中的最大者,即为最大子段和.
 * auther: cm
 * date: 2010/11/20
 */
public class MaxSubSumRec 
{
	private static int maxSumRec(int[] a, int left, int right)
	{
		if (left == right)
		{
			if (a[left] > 0)
			{
				return a[left];
			}
			else
			{
				return 0;
			}
		}

		int center = (left + right) / 2;
		int maxLeftSum = maxSumRec(a, left, center);
		int maxRightSum = maxSumRec(a, center + 1, right);

		int maxLeftBorderSum = 0;
		int leftBorderSum = 0;
		for (int i = center; i >= left; i--)
		{
			leftBorderSum += a[i];
			if (leftBorderSum > maxLeftBorderSum)
			{
				maxLeftBorderSum = leftBorderSum;
			}
		}

		int maxRightBorderSum = 0;
		int rightBorderSum = 0;
		for (int i = center + 1; i <= right; i++)
		{
			rightBorderSum += a[i];
			if (rightBorderSum > maxRightBorderSum)
			{
				maxRightBorderSum = rightBorderSum;
			}
		}

		return max(maxLeftSum, maxRightSum, maxRightBorderSum + maxLeftBorderSum);
	}

	//入口程序
	public static int maxSubSum(int[] a)
	{
		return maxSumRec(a, 0, a.length - 1);
	}

	//求三数中的最大值
	private static int max(int a, int b, int c)
	{
		int max = a > b ? a : b;
		max = c > max ? c : max;

		return max;
	}

	public static void main(String[] args) 
	{
		int[] a = {-2, 11, -4, 13, -5, -2};
		System.out.println(MaxSubSumRec.maxSubSum(a));
	}
}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值