[leet code] Maximum Subarray

来源:互联网 发布:伪娘专用阴茎套淘宝 编辑:程序博客网 时间:2024/05/16 10:39

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray [4,−1,2,1] has the largest sum = 6.

click to show more practice.

More practice:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

该题思路最重要, 最初想法是储存所有结果为正的子数组的sum到一个新建数组当中, 然后再提取该结果数组最大值作为返回值.  但经过多次尝试能无法实现.

经网上搜索后发现可以引入一个max变量动态储存子数组结果, 使得只有子数组最大值被保留并用于与新的子数组结果进行比较.  另一方面, 只要子数组的选取不需要考虑大小比较, 而只要结果为正则继续增加下一个数组元素.

public class Solution {    public int maxSubArray(int[] A) {        int sum = 0;        int max = Integer.MIN_VALUE;// ensure the initial value < all the array elements                for (int i=0; i<A.length; i++){            // keep culculating sum of subarray            sum += A[i];            // keep the max sum of subarrays            max = Math.max(max,sum);            // reset sum if sum<0; if all the array elements < 0, then return the single largest array element            if(sum<0) sum = 0;        }        return max;    }}

Divide and conquer approach:

这是目前接触到的最难的题目(做的题还很少).  即使是看了别人的解决方法还需要很长一段时间理解.  该解决方法的思路是将最大subarray的情况分成三种:

1. 最大subarray完全在数组中点左边

2. 最大subarray完全在数组中点右边

3. 最大subarray经过数组中点

然后在得到情况1和情况2的时候都使用递归, 而为了理解这个做法我曾经manually模拟运行, 过程感觉比较复杂.  回归的程序的实际当中其实可以不需要考虑到每一步的细节儿只需要考虑一下几点:

1. 递归的输入

2. 递归的输出

3. 递归的出口

于是回到本体思路, 在计算最大subarray的函数当中, 我需要计算上面提到的三种情况subarray的最大值, 再从这三种情况的最大值当中选最大值作为返回.

note: 经过递归, 情况1 和情况2 其实都会最终回到情况3. 另, midLeftMax 与midRightMax没有使用MIN_VALUE, 因为在所有subarray元素都为负值时, 只有最小元素会返回.  而在情况3下(subarray会经过中点), 返回的只可能是中点, 于是左右均可以设为0;

public class Solution {    public int maxSubArray(int[] A) {        if (A.length == 0) return Integer.MIN_VALUE;                int sumMax = Integer.MIN_VALUE;        return findSubSum(A, 0, A.length-1, sumMax);    }        // recursive function    public int findSubSum(int[] A, int left, int right, int sumMax){        // recursive exit        if(left>right) return Integer.MIN_VALUE;                int mid = (left+right)/2;        //case left        int leftMax = findSubSum(A, left, mid-1, sumMax);        // case right        int rightMax = findSubSum(A, mid+1, right, sumMax);                // case cross mid        int sum = 0;        // mid->left        int midLeftMax = 0;        for (int i=mid-1; i>=left; i--){            sum += A[i];            midLeftMax = Math.max(midLeftMax, sum);        }                //mid->right        int midRightMax = 0; sum=0;        for (int i=mid+1; i<=right; i++){            sum += A[i];            midRightMax = Math.max(midRightMax, sum);        }                //max sum        sumMax = Math.max(Math.max(leftMax, rightMax), midLeftMax+midRightMax+A[mid]);        return sumMax;    }}





0 0
原创粉丝点击