分治算法---最大子数组

该算法核心思想:
任何连续最大子数组必然处于以下三种情况:

  1. 子数组完全落在中点左边
  2. 子数组完全落在中点右边
  3. 子数组横跨中点

所以先求出左边最大的子数组,再找出右边的,然后从中间找。比较大小即可。

中间点的最大子数组容易确定,左右两边的无法确定,所以需要递归,把左右两边的数组分解到只剩一个元素时就能轻松确定。

class MaxRange{
    int start;
    int end;
    int sum;

    public MaxRange(int max, int maxLeftIndex, int maxRightIndex) {
        this.start=maxLeftIndex;
        this.end=maxRightIndex;
        this.sum=max;
    }
}
 public MaxRange findMaxMumSubArray(int[] array,int left,int right){
        if (left==right){
            return new MaxRange(array[left],left,right);
        }
        else {
            int mid=(left+right)/2;

            MaxRange maxRangeLeft=findMaxMumSubArray(array,left,mid);
            MaxRange maxRangeRight=findMaxMumSubArray(array,mid+1,right);
            MaxRange maxRangeCross=findCrossMax(array,left,mid,right);


            return getMax(maxRangeLeft,maxRangeCross,maxRangeRight);
        }
    }
 public MaxRange findCrossMax(int[] array,int left,int mid,int right) {
        int sum=0;
        int max=sum;
        int maxLeftIndex=mid;
        for (int i=maxLeftIndex;i>=left;i--){
            sum+=array[i];
            if (sum>max){
                max=sum;
                maxLeftIndex=i;
            }
        }
        sum=max;
        if (max<=0){
            maxLeftIndex=mid+1;
        }
        int maxRightIndex=mid;
        for (int i=maxRightIndex+1;i<=right;i++){
            sum+=array[i];
            if (sum>max){
                max=sum;
                maxRightIndex=i;
            }
        }
        return new MaxRange(max,maxLeftIndex,maxRightIndex);
    }
public static void main(String[] args) {
        Suanfa1 s= new Suanfa1();
        Random random=new Random();
        int array[]=new int[8];
        for (int i=0;i<array.length;i++){
            int rand=random.nextInt(1000);
            rand=random.nextInt(2)==0?rand*-1:rand;
            array[i]=rand;
        }
        for (int a:array){
            System.out.print(a+"__");
        }
        System.out.println("------------");
        System.out.println("");
        MaxRange maxRange=s.findMaxMumSubArray(array,0,array.length-1);
        for (int i=maxRange.start;i<=maxRange.end;i++){
            System.out.print(array[i]+"__");
        }
    }
    运行结果:
    246__-82__816__-193__-656__-834__865__645__------------
    865__645__


555__755__657__117__-262__-158__-662__-514__------------

555__755__657__117__

851__-893__-882__-126__-850__806__-16__936__------------

806__-16__936__
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值