Description

Given an array of integers, find two non-overlapping subarrays which have the largest sum. The number in each subarray should be contiguous. Return the largest sum.

Example

For given[1, 3, -1, 2, -1, 2], the two subarrays are[1, 3]and[2, -1, 2]or[1, 3, -1, 2]and[2], they both have the largest sum 7.

Solution

1.找两个不相交的subarray可以转化为以某个index i为分水岭,将数组分隔成两个数组,左数组和有数组分别找sum最大的subarray。这样就转换成了跟maximum subarray相似的问题。在左数组中找max subarray等同于maximum subarray I,而在右数组中找max subarray按照maximum subarray I的思路,反向遍历即可。

2.不同于maximum subarray I的一点是,I中只要用一个变量max,在遍历过程中反复比对得出最终的结果即可,但在这一题中,因为不确定作为分水岭的index i究竟是哪一个,所以需要把所有遍历过程中得到的max值存下来
local[i]代表以第i个数结尾的所有subarray的最大sum
global[i]代表前i个数中所有subarray的最大sum
从左往右遍历时local[i] = max(local[i-1] + n[i], n[i]), global[i] = max(global[i-1], local[i])
从右往左遍历时local[i] = max(local[i+1] + n[i], n[i]), global[i] = max(global[i+1], local[i])

3.得到globalLeft和globalRight后,在重新遍历一边数组,确定作为左右分割点的index i即可,max = max(max, globalLeft[i] + globalLeft[i+1])

public class Solution {
    /**
     * @param nums: A list of integers
     * @return: An integer denotes the sum of max two non-overlapping subarrays
     */
    public int maxTwoSubArrays(ArrayList<Integer> nums) {
        // write your code
        int[] localLeft = new int[nums.size()];
        int[] globalLeft = new int[nums.size()];
        localLeft[0] = nums.get(0);
        globalLeft[0] = nums.get(0);
        for (int i = 1; i < nums.size(); i++) {
            localLeft[i] = Math.max(localLeft[i-1] + nums.get(i), nums.get(i));
            globalLeft[i] = Math.max(globalLeft[i-1], localLeft[i]);
        }

        int[] localRight = new int[nums.size()];
        int[] globalRight = new int[nums.size()];
        localRight[nums.size()-1] = nums.get(nums.size()-1);
        globalRight[nums.size()-1] = nums.get(nums.size()-1);
        for (int i = nums.size()-2; i >= 0; i--) {
            localRight[i] = Math.max(localRight[i+1] + nums.get(i), nums.get(i));
            globalRight[i] = Math.max(globalRight[i+1], localRight[i]);
        }

        int max = Integer.MIN_VALUE;
        for (int i = 0; i < nums.size()-1; i++) {
            max = Math.max(max, globalLeft[i] + globalRight[i+1]);
        }

        return max;
    }
}

results matching ""

    No results matching ""