https://leetcode-cn.com/problems/reverse-subarray-to-maximize-array-value/
1.翻转一个子数组,数组值只有子数组的端点变,其他没有变化,首先求出一个原数组的数组值,然后找出两个端点,使增加最大。
简单的使用O(N^2),数据太大了,复杂度要O(N)
前两个项涉及两个下标,后面两个项都只有一个下标,这就需要枚举两个点,要拆这两项,只涉及一个点。拆绝对值有正负两种情况,两个绝对值,有4种情况。正正、正负、负正、负负四种情况。
这四种情况选择最大的,因为两个绝对值正数加起来,所以是最大。
这就拆成只涉及一个下标的情况,都是加起来,两边选择最大值,合起来就是最大的。
开始和结束需要单独考虑。
class Solution {
public:
int fac1[30005];
int fac2[30005];
int n;
int get_max(int * a){
int ret=a[1];
for(int i=2;i<n-1;i++){
ret=max(ret,a[i]);
}
return ret;
}
int maxValueAfterReverse(vector<int>& arr) {
n=arr.size();
int ori=0;
for(int i=0;i<n-1;i++){
int diff=abs(arr[i]-arr[i+1]);
ori+=diff;
}
int sign[4][4]={
{1,-1,-1,1},
{1,1,-1,-1},
{-1,-1,1,1},
{-1,1,1,-1},
};
int diff=0;
for(int iter=0;iter<4;iter++){
for(int i=1;i<n-1;i++){
fac1[i]=sign[iter][0]*arr[i] + sign[iter][1]*arr[i+1] - abs(arr[i]-arr[i+1]);
fac2[i]=sign[iter][2]*arr[i-1] + sign[iter][3]*arr[i] - abs(arr[i]-arr[i-1]);
}
int e1=get_max(fac1);
int e2=get_max(fac2);
diff=max(diff,e1+e2);
}
for(int j=1;j<n-1;j++){
diff=max(diff,abs(arr[j+1]-arr[0])-abs(arr[j+1]-arr[j]));
}
for(int i=1;i<n-1;i++){
diff=max(diff,abs(arr[n-1]-arr[i-1])-abs(arr[i]-arr[i-1]));
}
return ori+diff;
}
};