算法 中等 | 45. 最大子数组差

算法 中等 | 45. 最大子数组差

题目描述

给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B)|最大。
返回这个最大的差值。

样例1

输入:[1, 2, -3, 1]
输出:6
解释:
子数组是 [1,2][-3].所以答案是 6.

样例2

输入:[0,-1]
输出:1
解释:
子数组是 [0][-1].所以答案是 1.

java题解

dp。
维护四个数组,当前位置左边的最大子数组和,最小子数组和。当前位置右边的最大子数组和,最小子数组和。
然后枚举分割线,扫描一下即可。

public class Solution {
    public int maxDiffSubArrays(int[] nums) {
        // write your code here
        int size = nums.length;
        int[] left_max = new int[size];
        int[] left_min = new int[size];
        int[] right_max = new int[size];
        int[] right_min = new int[size];
        int[] copy = new int[size];
        /*Get negative copy*/
        for(int i = 0; i < size; i++){
            copy[i] = -1 * nums[i];
        }
        int max = Integer.MIN_VALUE;
        int sum = 0;
        int minSum = 0;
        /*Forward: get max subarray*/
        for(int i = 0; i < size; i++){
            sum += nums[i];
            max = Math.max(max, sum - minSum);
            minSum = Math.min(sum, minSum);
            left_max[i] = max;
        }
        /*Backward: get max subarray*/
        max = Integer.MIN_VALUE;
        sum = 0;
        minSum = 0;
        for(int i = size - 1; i >= 0; i--){
            sum += nums[i];
            max = Math.max(max, sum - minSum);
            minSum = Math.min(sum, minSum);
            right_max[i] = max;
        }
        /*Forward: get min subarray*/
        max = Integer.MIN_VALUE;
        sum = 0;
        minSum = 0;
        for(int i = 0; i < size; i++){
            sum += copy[i];
            max = Math.max(max, sum - minSum);
            minSum = Math.min(sum, minSum);
            left_min[i] = -1 * max;
        }
        /*Backward: get min subarray*/
        max = Integer.MIN_VALUE;
        sum = 0;
        minSum = 0;
        for(int i = size - 1; i >= 0; i--){
            sum += copy[i];
            max = Math.max(max, sum - minSum);
            minSum = Math.min(sum, minSum);
            right_min[i] = -1 * max;
        }
        int diff = 0;
        for(int i = 0; i < size - 1; i++){
            diff = Math.max(diff, Math.abs(left_max[i] - right_min[i + 1]));
            diff = Math.max(diff, Math.abs(left_min[i] - right_max[i + 1]));
        }
        return diff;
    }
}

C++题解

dp。
维护四个数组,当前位置左边的最大子数组和,最小子数组和。当前位置右边的最大子数组和,最小子数组和。
然后枚举分割线,扫描一下即可。

class Solution {
public:
	int maxDiffSubArrays(vector<int> nums) {
	    const int n = nums.size();
	    if (n < 2) {
	        return 0;
	    }
	    vector<int> lMax(n), rMax(n), lMin(n), rMin(n);
	    for (int i = 0, peek = INT_MIN, cur = 0; i < n; i++) {
	        cur += nums[i];
	        peek = max(peek, cur);
	        lMax[i] = peek;
	        if (cur < 0) {
	            cur = 0;
	        }
	    }
	    for (int i = n - 1, peek = INT_MIN, cur = 0; i > 0; i--) {
	        cur += nums[i];
	        peek = max(peek, cur);
	        rMax[i - 1] = peek;
	        if (cur < 0) {
	            cur = 0;
	        }
	    }
	    for (int i = 0, peek = INT_MAX, cur = 0; i < n; i++) {
	        cur += nums[i];
	        peek = min(cur, peek);
	        lMin[i] = peek;
	        if (cur > 0) {
	            cur = 0;
	        }
	    }
	    for (int i = n - 1, peek = INT_MAX, cur = 0; i > 0; i--) {
	        cur += nums[i];
	        peek = min(peek, cur);
	        rMin[i - 1] = peek;
	        if (cur > 0) {
	            cur = 0;
	        }
	    }
	    int result = INT_MIN;
	    for (int i = 0; i < n - 1; i++) {
	        int temp = max(lMax[i] - rMin[i], rMax[i] - lMin[i]);
	        result = max(result, temp);
	    }
	    return result;
	}
};

python题解

dp。
维护四个数组,当前位置左边的最大子数组和,最小子数组和。当前位置右边的最大子数组和,最小子数组和。
然后枚举分割线,扫描一下即可。

class Solution:
    def maxDiffSubArrays(self, nums):
        # write your code here
        n = len(nums)
        mx1 = [0]*n
        mx1[0] = nums[0]
        mn1 = [0]*n
        mn1[0] = nums[0]
        forward = [mn1[0], mx1[0]]
        array_f = [0]*n
        array_f[0] = forward[:]
        for i in range(1, n):
            mx1[i] = max(mx1[i-1] + nums[i], nums[i])
            mn1[i] = min(mn1[i-1] + nums[i], nums[i])
            forward = [min(mn1[i], forward[0]), max(mx1[i], forward[1])]
            array_f[i] = forward[:]
        mx2 = [0]*n
        mx2[n-1] = nums[n-1]
        mn2 = [0]*n
        mn2[n-1] = nums[n-1]
        backward = [mn2[n-1], mx2[n-1]]
        array_b = [0]*n
        array_b[n-1] = backward[:] 
        for i in range(n-2, -1, -1):
            mx2[i] = max(mx2[i+1] + nums[i], nums[i])
            mn2[i] = min(mn2[i+1] + nums[i], nums[i])
            backward = [min(mn2[i], backward[0]), max(mx2[i], backward[1])]
            array_b[i] = backward[:]
        result = -65535
        for i in range(n-1):
            result = max(result, abs(array_f[i][0] - array_b[i+1][1]), abs(array_f[i][1] - array_b[i+1][0]))
        return result
发布了201 篇原创文章 · 获赞 31 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43233085/article/details/104167829
今日推荐