获得连续子数组的最大和(见算法导论第三版第三章)

package com.sortdemo;
/**
 * 获得连续子数组的最大和
 *
 */
public class MaxSubArraySum {

	private static long getMax(long a, long b) {
		return a > b ? a : b;
	}
	/**
	 * 获得连续子数组的最大和
	 * 隐含的问题:
	 * 1.所有负值的最大值
	 * 2.所有正值的和
	 * 3.此程序很好的把1、2结合在一起了,可以解决获得连续子数组的最大和问题
	 * @return 最大和,此处用了Long型是为了表示当参数为null或空时,可以返回null,返回其它任何数字都可能引起歧义。
	 */
	public static Long getMax(int[] array) {
		
		if (array == null || array.length <= 0) {
			return null;
		}
		
		long maxSum = array[0]; //所有子数组中最大的和
		long righteEdge = array[0]; //右侧子数组的最大和
		for (int i = 1; i < array.length; i++) {
			// 若是没有此限定条件,可以看出程序是纯粹的累加所有值
			if (righteEdge < 0) {//以0为界、更新其值。。。可以拆分为负值的最大值
				righteEdge = array[i];
			} else { 
				righteEdge += array[i];
			}
			//对所有子数组中和的值进行不断更新
			maxSum = getMax(righteEdge, maxSum);
		}
		return maxSum;
	}

	public static void main(String[] args) {
		int[] array = {-1, -2, 3, -10, -4, 1, 2, -5};
		System.out.println("Max sum: " + MaxSubArraySum.getMax(array));
	}

}

上面的方法是扫描法,性能优异呀 。。。

package com.sortdemo;

class  FindMaxSubMatrix
{
	
	static int maxLeft = 0; //记录并更新当前下标
	static int maxRight = 0;
	//分治法
	public static int findMaxCrossSubMatrix(int []A, int low, int mid, int high)
	{
		int leftSum = -10000000;   //保存目前为止找到的最大和
		int sumL = 0;              //保存A[i..mid]中所有和的值
		for(int i = mid; i >= low; i--)
		{
			sumL = sumL + A[i];
			if(sumL > leftSum){      //每找到一个子数组A[i..mid]的和大于leftsum时候,更新值
				leftSum = sumL;
				maxLeft = i;
			}				
		}

		int rightSum = -10000000;
		int sumR = 0;            
		for(int i = mid + 1; i <= high; i++)
		{
			sumR += A[i];
			if(sumR > rightSum){
				rightSum = sumR;
				maxRight = i;
			}
		}
		
		return leftSum + rightSum;
	}
	
	public  static int findMaxSubMatrix(int []A, int p, int q)
	{
		int left_sum, right_sum, cross_sum;
	    if (p == q)  //一个元素
	    {
	        return A[q];
	    }
	    else
	    {
	        int mid = (q + p) / 2; //分治
	        left_sum = findMaxSubMatrix(A, p, mid);  //前半部
	        right_sum = findMaxSubMatrix(A, mid + 1, q);  //后半部
	        cross_sum = findMaxCrossSubMatrix(A, p, mid, q);  //跨越前后
	 
	        if (left_sum >= right_sum && left_sum >= cross_sum)  //最大子数组在左边
	            return left_sum;
	 
	        else if (right_sum >= left_sum && right_sum >= cross_sum)  //右边
	            return right_sum;
	 
	        else  //跨越
	            return cross_sum;
	    }
		
	}

	public static void main(String[] args) 
	{
		int []A = {2,-4,9,1,12,-2,-5,4,-6,10};
		int sumArr = findMaxSubMatrix(A,0,A.length-1);
		System.out.println(sumArr);
		System.out.println(maxLeft);
		System.out.println(maxRight);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值