http://www.lintcode.com/zh-cn/problem/maximum-subarray-difference/#
这个问题和最大化两个不重叠子数组和类似,即还是想办法求得区间[0...i]
和[i+1...n-1]
的最大/小连续子数组和,只是不同的是要最大化相减的绝对值。那么就对两个区间都分别预处理好最大值和最小值,答案一定是其中一个的最大值与另一个的最小值之差。
int maxDiffSubArrays(vector<int> &nums) {
if (nums.empty()) return 0;
int n = nums.size();
// 思路:对所有的i,分别预处理好区间[0...i]和[i+1...n-1]的子数组最大值和最小值
// 然后结果是max(left_max[i] - right_min[i+1]), max(left_min[i] - right_max[i])两个较大的那个
vector<int> left_max(n), left_min(n), right_max(n), right_min(n);
int prev_max = nums[0], prev_min = nums[0], cur_max, cur_min;
left_max[0] = nums[0]; left_min[0] = nums[0];
for (int i = 1; i < n - 1; ++i) {
if (prev_max > 0) cur_max = prev_max + nums[i];
else cur_max = nums[i];
if (prev_min < 0) cur_min = prev_min + nums[i];
else cur_min = nums[i];
left_max[i] = max(left_max[i-1], cur_max);
left_min[i] = min(left_min[i-1], cur_min);
prev_max = cur_max;
prev_min = cur_min;
}
prev_max = nums[n-1]; prev_min = nums[n-1];
right_max[n-1] = nums[n-1]; right_min[n-1] = nums[n-1];
for (int i = n - 2; i > 0; --i) {
if (prev_max > 0) cur_max = prev_max + nums[i];
else cur_max = nums[i];
if (prev_min < 0) cur_min = prev_min + nums[i];
else cur_min = nums[i];
right_max[i] = max(right_max[i+1], cur_max);
right_min[i] = min(right_min[i+1], cur_min);
prev_max = cur_max;
prev_min = cur_min;
}
int ret = 0;
for (int i = 0; i < n - 1; ++i) {
ret = max(ret, max(abs(left_max[i]-right_min[i+1]), abs(left_min[i]-right_max[i+1])));
}
return ret;
}