分治法求解最大子數組問題

最大子數組:求連續數組的最大和問題,也就是說數組的那個連續子數組的和最大.(我的理解)算法

    主要思想經過分治法,最大子數組只能有三種狀況:中間元素的左邊取得;中間元素的右邊取得;跨越中間元素取得.  能夠經過mind=(low+high)/2分解,把元問題分解成更小的子問題。數組

代碼以下     ArrarType表示找到的最大子數組相應的左右邊界和值ide

package com.lifeStudy.algorith;

public class ArrarTypes {
    private int max_left;
    private int max_right;
    private int max_sum;

    @Override
    public String toString() {
        return "ArrarTypes:  max_left=" + max_left + "  max_right=" + max_right + "   max_sum=" + max_sum;
    }

    public ArrarTypes(int max_left, int max_right, int max_sum) {
        this.max_left = max_left;
        this.max_right = max_right;
        this.max_sum = max_sum;
    }

    public void setMax_left(int max_left) {
        this.max_left = max_left;
    }

    public void setMax_right(int max_right) {
        this.max_right = max_right;
    }

    public void setMax_sum(int max_sum) {
        this.max_sum = max_sum;
    }

    public int getMax_left() {
        return max_left;
    }

    public int getMax_right() {
        return max_right;
    }

    public int getMax_sum() {
        return max_sum;
    }
}

 

 

求解算法代碼this

package com.lifeStudy.algorith;


//求解最小子數組問題  分治法
public class TheMaxSubArray {


    /**
     * @param A    待求數組
     * @param low  最小的位置序列
     * @param mid  中間的位置序列
     * @param high 最大的位置序列
     * @return 返回數組A 中跨越中間位置的最大數組和  包括起始和結束邊界、最大的和值
     */

    //求出數組A跨越中點mid的最大數組和
    public static ArrarTypes find_max_crossing_subArray(int[] A, int low, int mid, int high) {


        //求出左邊數據的最大和
        int left_sum = Integer.MIN_VALUE;
        int max_left = mid;//記錄左邊最大和的邊界位置
        int sum = 0;
        for (int i = mid; i >= low; i--) {
            sum += A[i];
            if (sum > left_sum) {
                left_sum = sum;
                max_left = i;
            }
        }
        //求出右邊數據的最大和

        int right_sum = Integer.MIN_VALUE;
        int max_right = mid + 1;
        sum = 0;
        for (int j = mid + 1; j <= high; j++) {

            sum += A[j];
            if (sum > right_sum) {
                right_sum = sum;
                max_right = j;
            }
        }
        return new ArrarTypes(max_left, max_right, left_sum + right_sum);
    }

    /**
     * @param A    目標數組
     * @param low  數組最小位置
     * @param high 數組最大位置
     * @return
     */
    //查找出最大和數組  包含三種狀況 在數組集合的左邊;在數組集合的右邊;跨越數組中心元素集合
    public static ArrarTypes find_max_subArray(int[] A, int low, int high) {

        if (low > high) {
            return null;
        }
        if (low == high) {
            return new ArrarTypes(low, high, A[low]);
        } else {
            int mid = (low + high) / 2;
            ArrarTypes max_subArrayleft = find_max_subArray(A, low, mid);
            ArrarTypes max_subArrayright = find_max_subArray(A, mid + 1, high);
            ArrarTypes max_crossing_subArray = find_max_crossing_subArray(A, low, mid, high);
            if (max_crossing_subArray.getMax_sum() > max_subArrayleft.getMax_sum() && max_crossing_subArray.getMax_sum() > max_subArrayright.getMax_sum()) {
                return max_crossing_subArray;
            } else if (max_subArrayleft.getMax_sum() > max_crossing_subArray.getMax_sum() && max_subArrayleft.getMax_sum() > max_subArrayright.getMax_sum()) {
                return max_subArrayleft;
            } else{
                return max_subArrayright;
            }
        }

    }


    public static void main(String... args) {
        int a[] = new int[]{13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
        ArrarTypes max_subArray = find_max_subArray(a, 0, a.length - 1);
        System.out.println(max_subArray.toString());
    }


}

 

   線性時間實現求最大子數組問題·spa

   原理:例如A[1.....j]的最大子數組已知,那麼A[1......j+1]的最大子數組要麼是前一個元素的最大子數組,或者是A[i....j+1]爲最大子數組
              能夠經過比較前一個最大子數組和邊界最大子數組(包含最後一個元素) 的大小code

package com.lifeStudy.algorith;

//求線性時間的最大子數組問題
public class TheMaxSubArrayLinearTime {
    //原理:例如A[1.....j]的最大子數組已知,那麼A[1......j+1]的最大子數組要麼是前一個元素的最大子數組,或者是A[i....j+1]爲最大子數組
    private static int[] boundryMax;//邊界最大子數組   當前元素的最大子數組等於前一個元素的最大子數組或者前一個元素的邊界子數組加當前元素或者等於當前元素
    private static int[] valueMax;//最大子數組
    private static int[][] pos;//最大子數組的邊界位置信息

    public static void InitDatas(int vales[]) {

        boundryMax = new int[vales.length];
        valueMax = new int[vales.length];
        //初始化第一個元素的邊界最大子數組和最大子數組
        boundryMax[0] = vales[0];
        valueMax[0] = vales[0];
        pos = new int[vales.length][2];
        pos[0][1] = pos[0][0] = 0;
        //求出每個子數組的最大子數組
        for (int i = 1; i < vales.length; i++) {
            int beforeValueMax = valueMax[i - 1];//前一個最大子數組
            int currentValue = vales[i];
            int beforeBoundryMax = boundryMax[i - 1] + currentValue;
            int max = beforeValueMax > currentValue ? (beforeValueMax > beforeBoundryMax ? beforeValueMax : beforeBoundryMax) : (currentValue > beforeBoundryMax ? currentValue : beforeBoundryMax);
            valueMax[i] = max;
            boundryMax[i] = beforeBoundryMax > currentValue ? beforeBoundryMax : currentValue;
        }
    }

    public static void main(String... args) {
        int a[] = new int[]{13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7, 0};
        InitDatas(a);
        System.out.println(valueMax[valueMax.length - 1]);
    }
}
相關文章
相關標籤/搜索