LeetCode 1330. 翻转子数组得到最大的数组值

https://leetcode-cn.com/problems/reverse-subarray-to-maximize-array-value/

1.翻转一个子数组,数组值只有子数组的端点变,其他没有变化,首先求出一个原数组的数组值,然后找出两个端点,使增加最大。

简单的使用O(N^2),数据太大了,复杂度要O(N)

abs(A_{j}-A_{i-1})+abs(A_{i}-A_{j+1})-abs(A_{i}-A_{i-1})-abs(A_{j}-A_{j+1})

前两个项涉及两个下标,后面两个项都只有一个下标,这就需要枚举两个点,要拆这两项,只涉及一个点。拆绝对值有正负两种情况,两个绝对值,有4种情况。正正、正负、负正、负负四种情况。

这四种情况选择最大的,因为两个绝对值正数加起来,所以是最大。

A_{j}-A_{j+1}-abs(A_{j}-A_{j+1})-A_{i-1}+A_{i}-abs(A_{i}-A_{i-1})

A_{j}+A_{j+1}-abs(A_{j}-A_{j+1})-A_{i-1}-A_{i}-abs(A_{i}-A_{i-1})

-A_{j}-A_{j+1}-abs(A_{j}-A_{j+1})+A_{i-1}+A_{i}-abs(A_{i}-A_{i-1})

-A_{j}+A_{j+1}-abs(A_{j}-A_{j+1})+A_{i-1}-A_{i}-abs(A_{i}-A_{i-1})

这就拆成只涉及一个下标的情况,都是加起来,两边选择最大值,合起来就是最大的。

开始和结束需要单独考虑。

 

 

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;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值