算法导论之最大子数组问题

6 篇文章 0 订阅
//寻找最大子数组,使该子数组元素之和为所有子数组中最大的
/*
 * 算法:
 * 1。利用分治策略,逐层寻找
 * 2.最大子数组存在三种情况:若将数组在中间元素位置划分为两部分,则最大子数组可能在中间元素的左半部分、右半部分或者是跨越中间元素的部分。
 * 3.现在我们将问题一分为三,在左半部分寻找最大子数组,在右半部分寻找最大子数组,以及在横跨中间的最大子数组中寻找三者之中最大的。而左右两半部分的情况其实是以上情况的递归呈现,所以我们只需针对第三种情况提出解决办法。
 * 4.寻找横跨中间位置的最大子数组可以将问题一分为二:我们确定中间元素,在中间元素的左边找最大的数组,右边找到最大的数组,两边的最大子数组可以确定一个边界,使得整个横跨数组为所有横跨数组中最大的一个。
 * 5.递归寻找左右两半部分的最大子数组。
 */
package offer.giveme;
public class SmallesSubArray {
    public SubArray findMaxInCrossingSubarray(int[] num,int low,int mid,int high){
    	int left_sum=Integer.MIN_VALUE;
    	int sum=0;
    	int max_left=mid;//记录使左半边子数组最大的左边界
    	for(int i=mid;i>=low;i--){
    		sum=sum+num[i];
    		if(sum>left_sum){
    			left_sum=sum;
    			max_left=i;
    		}
    	}
    	int right_sum=Integer.MIN_VALUE;
    	sum=0;
    	int max_right=mid+1;
    	for(int i=mid+1;i<=high;i++){
    		sum=sum+num[i];
    		if(sum>right_sum){
    			right_sum=sum;
    		    max_right=i;
    		}
    	}
    	sum=left_sum+right_sum;
    	return new SubArray(max_left,max_right,sum);
    }
    public SubArray findMaxSubarray(int[] num,int low,int high){

    	if(high==low){
    		return new SubArray(low,high,num[low]);
    	}
    	else {
    		int mid=(low+high)/2;
    		SubArray leftSub=findMaxSubarray(num,low,mid);
    		SubArray rightSub=findMaxSubarray(num,mid+1,high);
    		SubArray crossSub=findMaxInCrossingSubarray(num,low,mid,high);
    		
    		if(leftSub.sum>=rightSub.sum&&leftSub.sum>=crossSub.sum)
    			return leftSub;
    		else if(rightSub.sum>=leftSub.sum&&rightSub.sum>=crossSub.sum)
    			return rightSub;
    		else
    			return crossSub;
    	}	
    }
	
	public static void main(String[] args) {
		int[] num={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
		SubArray subarray=new SmallesSubArray().findMaxSubarray(num,0,num.length-1);
		System.out.println("high:"+subarray.high);
		System.out.println("low:"+subarray.low);
		System.out.println("sum:"+subarray.sum);
		for(int i=subarray.low;i<=subarray.high;i++){
			System.out.print(num[i]+" ");
		}
	}
}


class SubArray{
	int low;
	int high;
	int sum=0;
	public SubArray(int low,int high,int sum){
		this.low=low;
		this.high=high;
		this.sum=sum;
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值