题目描述:
给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B)|最大。
返回这个最大的差值。
注意事项:
子数组最少包含一个数
样例:
给出数组[1, 2, -3, 1],返回 6
挑战:
时间复杂度为O(n),空间复杂度为O(n)
思路讲解:
首先我们看一下要求,即将|SUM(A) - SUM(B)|最大,其有两种情况可以求得最大值第一种是A最大、B最小;第二种是A最小、B最大,由于数组A、B是不重叠的,所以我们只需要将这个数组任意分成两段,然后在每一段中求出最大值和最小值,然后将前面一段的最大值减去后面一段的最小值与前面一段的最小值减去后面一段的最大值相比较这样我们就得到了这一种分法的最大子数组差,我们然后将不同分法的最大子数组差比较,进而可以得到最大子数组差。这样题目就得到解决了。
个人走的一点弯路:
后面我试了一下,外循环是分法然后每次分法求得的最大子数组差,后面发现跑到79%就time limited,经过思考,得到原来是我们求最大值或者最小值时,由于我们外层是分法的循环,这样就导致我们每次分法的时候都要从0开始计算最大值或者最小值,所以我们直接用一个数组存储最大值或者最小值。beforemax[i]表示从前面到i的最大值。这样我们一个循环就能得到所有分法的节点的最大值或者最小值。这样就可以了。
代码详解:
class Solution {
public:
/*
* @param nums: A list of integers
* @return: An integer indicate the value of maximum difference between two substrings
*/
int maxDiffSubArrays(vector<int> &nums) {
// write your code here
int length=nums.size();
int *beforemax=new int[length];
int *aftermin=new int[length];
int *beforemin=new int[length];
int *aftermax=new int[length];
int max=nums[0];
int min=nums[0];
int curmax=nums[0],curmin=nums[0];
beforemax[0]=nums[0];//对数组的特殊位置进行初始化
beforemin[0]=nums[0];
aftermax[length-1]=nums[length-1];
aftermin[length-1]=nums[length-1];
for(int i=1;i<length;i++)//求从前向后的最大值和最小值
{
if(curmax<0){
curmax=nums[i];
}
else{
curmax=curmax+nums[i];
}
if(curmax>max)
{
max=curmax;
}
beforemax[i]=max;
if(curmin>0)
{
curmin=nums[i];
}else{
curmin+=nums[i];
}
if(curmin<min)
{
min=curmin;
}
beforemin[i]=min;
}
printarray(beforemax,length);
printarray(beforemin,length);
max=nums[length-1];
min=nums[length-1];
curmax=nums[length-1];
curmin=nums[length-1];
for(int i=length-2;i>=0;i--)//从后面往前求最大值或者最小值
{
if(curmax<0)
{
curmax=nums[i];
}else{
curmax=curmax+nums[i];
}
if(curmax>max)
{
max=curmax;
}
aftermax[i]=max;
if(curmin>0)
{
curmin=nums[i];
}else{
curmin+=nums[i];
}
if(curmin<min){
min=curmin;
}
aftermin[i]=min;
}
printarray(aftermax,length);
printarray(aftermin,length);
int max1;
int max2;
int max_now;
int res=0;
for(int i=0;i<length-1;i++){//不同分法的最大子数组差进行比较,进而得到最大的最大子数组差
max1=abs(beforemax[i]-aftermin[i+1]);
max2=abs(beforemin[i]-aftermax[i+1]);
max_now=max1>max2?max1:max2;
if(max_now>res)
{
res=max_now;
}
}
return res;
}
void printarray(int *array,int length)//将数组输出,检查求最大值或者最小值是否正确
{
for(int i=0;i<length;i++)
{
cout<<array[i]<<" ";
}
cout<<endl;
}
};