求解最大子数组

来源:互联网 发布:ubuntu清空文件夹 编辑:程序博客网 时间:2024/06/11 23:59

求解最大子数组

  • 问题描述,神马是最大子数组

    假定我们一个已知的数组为:

    int numbers[]={1,2,6,3,-5,-7,1,-6,8};

    现在我们需要求解其中某几个数之和最大的一段子数组,如果不考虑方法的复杂性,首先我们可以考虑暴力求解,即将所有可能的组合进行排列组合。那么我们可以得到n*(n-1)/2(不考虑顺序的排列组合)种可能,其复杂度为O(n^2)。

  • 为求得更好的解题思路,我们可以考虑使用分治法。

    1. 首先我们将数组按照中点分成两个部分
      这里写图片描述
      这样求解最大子数组的问题就变成了求左边部分,右边部分,跨过中间部分的最大子数组,其中求解左边和右边与求解整个数组的最大子数组逻辑相同。关键在于如何求解中间部分的最大子数组。

    2. 对于求解中间部分的最大子数组,由于该数组会经过中点,所以可以分解为两部分,分别为从middle向左出发,到左边某个index的最大值以及从middle出发,到右边某个index的最大值。将两个部分的最大值相加即可得到跨过中点的最大子数组,其时间复杂度为O(n);其基本实现如下:

      public static Model findCrossMiddle(int leftIndex,int middle,int rightIndex){    int leftSum=Integer.MIN_VALUE;    int leftRes=middle;    int rightSum=Integer.MIN_VALUE;    int rightRes=middle+1;    int sum=0;    for(int i=middle;i>=leftIndex;i--){        sum+=numbers[i];        if(sum>leftSum){            leftSum=sum;            leftRes=i;        }    }     //从middle向左出发,到左边某个index的最大值,并记录下标    sum=0;    for(int j=middle+1;j<=rightIndex;j++){        sum+=numbers[j];        if(sum>rightSum){            rightSum=sum;            rightRes=j;        }    }   //从middle向左出发,到左边某个index的最大值,并记录下标    return new Model(leftRes,rightRes,(leftSum+rightSum));}
  • 实现算法

    分析完基本实现思路,很自然就想到通过递归完成算法,要想通过递归,就要先知道算法的结束条件。在这里就是当划分的子数组只有一个元素时,则直接返回。在每次递归的时候,比较左中右三段中的哪个最大子数组最大,并返回表示该段中的最大子数组。

    其完整实现代码如下:

    public class MaxChildArray {    private static int numbers[]={1,2,6,3,1,8};    public static void main(String[] args) {        Model res=findMaxChildArray(0,numbers.length-1);        System.out.println(res);    }    //查找最大子数组的递归方法    public static Model findMaxChildArray(int leftIndex,int rightIndex){        if(leftIndex==rightIndex){            return new Model(leftIndex,rightIndex,numbers[leftIndex]);        }        else{            int middle=((leftIndex+rightIndex)/2);            Model modelLeft=findMaxChildArray(leftIndex,middle);            Model modelRight=findMaxChildArray(middle+1, rightIndex);            Model acrossModel=findCrossMiddle(leftIndex,middle,rightIndex);            if(modelLeft.getSum()>=modelRight.getSum()&&modelLeft.getSum()>=acrossModel.getSum()){                return modelLeft;            }            else if(modelRight.getSum()>=modelLeft.getSum()&&modelRight.getSum()>=acrossModel.getSum()){                return modelRight;            }            else{                return acrossModel;            }        }    }    //查找经过中点的最大子数组    public static Model findCrossMiddle(int leftIndex,int middle,int rightIndex){        int leftSum=Integer.MIN_VALUE;        int leftRes=middle;        int rightSum=Integer.MIN_VALUE;        int rightRes=middle+1;        int sum=0;        for(int i=middle;i>=leftIndex;i--){            sum+=numbers[i];            if(sum>leftSum){                leftSum=sum;                leftRes=i;            }        }        sum=0;        for(int j=middle+1;j<=rightIndex;j++){            sum+=numbers[j];            if(sum>rightSum){                rightSum=sum;                rightRes=j;            }        }        return new Model(leftRes,rightRes,(leftSum+rightSum));    }    //定义数据模型    public static class Model{        private int leftIndex;        private int rightIndex;        private int sum;        public Model(int leftIndex, int rightIndex, int sum) {            super();            this.leftIndex = leftIndex;            this.rightIndex = rightIndex;            this.sum = sum;        }        public int getLeftIndex() {            return leftIndex;        }        public void setLeftIndex(int leftIndex) {            this.leftIndex = leftIndex;        }        public int getRightIndex() {            return rightIndex;        }        public void setRightIndex(int rightIndex) {            this.rightIndex = rightIndex;        }        public int getSum() {            return sum;        }        public void setSum(int sum) {            this.sum = sum;        }        @Override        public String toString() {            return "Model [leftIndex=" + leftIndex + ", rightIndex=" + rightIndex + ", sum=" + sum + "]";        }       }   }

0 0