给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B)|最大。
返回这个最大的差值。
输入:[1, 2, -3, 1]
输出:6
解释:
子数组是 [1,2] 和[-3].所以答案是 6.
输入:[0,-1]
输出:1
解释:
子数组是 [0] 和 [-1].所以答案是 1.
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;
}
}
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;
}
};
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