leetcode 绝对值表达式的最大值c++

给你两个长度相等的整数数组,返回下面表达式的最大值:
∣ a r r 1 [ i ] − a r r 1 [ j ] ∣ + ∣ a r r 2 [ i ] − a r r 2 [ j ] ∣ + ∣ i − j ∣ |arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j| arr1[i]arr1[j]+arr2[i]arr2[j]+ij
其中下标 i,j 满足 0 <= i, j < arr1.length。

输入:arr1 = [1,2,3,4], arr2 = [-1,4,5,6]
输出:13
输入:arr1 = [1,-2,-5,0,10], arr2 = [0,-2,-1,-7,-4]
输出:20

分析:

这道题目看起来很简单但是 leetcode 上时间复杂度不优化使用暴力法是无法通过的

方法一:暴力法
class Solution {
public:
    int maxAbsValExpr(vector<int>& arr1, vector<int>& arr2) {
        int res=INT_MIN;
        for(int i=0;i<arr1.size();i++)
        {
            for(int j=i+1;j<arr1.size();j++)
            {
                res=max(res,abs(arr1[i]-arr1[j])+abs(arr2[i] - arr2[j])+abs(i-j));
            }
        }
        return res;
    }
};

这个时间复杂度不够好,所以不能够通过
时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( 1 ) O(1) O(1)

方法二:将问题变成一个数组的问题
  • 若 arr1[i]与arr2[i],arr1[j]与arr2[j] 的值都是同时大于0,或者同时小于0。就可以将两个数组的值相加变成一个数组 a[i][0]=arr1[i]+arr2[i]。在将数组通过按照值大小排序。然后用双指针的办法。
  • 若arr1[i]与arr2[i],arr1[j]与arr2[j]是一个小于0,一个大于0,那么这个时候我们就要用差来形成以数组c[i][0]=arr1[i]-arr2[i]。用双指针的办法。

例子:
同 index 值符号相同的情况

arr1=[1,-1,4,-5],arr2=[3,-2,1,-1]
a=[[4,0],[-3,1],[5,2],[-6,3]]
排序后a=[[-6,3],[-3,1],[4,0],[5,2]]
会发现这种情况对a操作和对arr1和arr2操作能得到相同的答案

同 index 值符号不同的情况

arr1=[1,-1,4,-5],arr2=[-3,2,-1,1]
a=[[4,0],[-3,1],[5,2],[-6,3]]
排序后a=[[-6,3],[-3,1],[4,0],[5,2]]
会发现这种情况对c操作和对arr1和arr2操作能得到相同的答案

那么同一个数组同时存在两种情况,说明我们需要包含所有情况,所以既要对a进行遍历,也要对c进行遍历

class Solution {
public:
    static bool cmp(vector<int> &a,vector<int>&b)//按值大小排序
    {
        return a[0]<b[0];
    }
    int maxAbsValExpr(vector<int>& arr1, vector<int>& arr2) {
        int res=INT_MIN;
        vector<vector<int>> a(arr1.size(),vector<int>(2));//和创建数组
        vector<vector<int>> c(arr1.size(),vector<int>(2));//差创建数组
        for(int i=0;i<arr1.size();i++)
        {
            a[i][0]=arr1[i]+arr2[i];
            a[i][1]=i;
        }
        for(int i=0;i<arr1.size();i++)
        {
            c[i][0]=arr1[i]-arr2[i];
            c[i][1]=i;
        }
        sort(a.begin(),a.end(),cmp);
        sort(c.begin(),c.end(),cmp);
        int i=0;
        int j=a.size()-1;
        
        //两种情况都遍历就包含所有情况
        while(i<j)
        {
            res=max(res,abs(a[i][0]-a[j][0])+abs(a[i][1]-a[j][1]));
            if(abs(a[i][1]-a[j-1][1])>abs(a[i][1]-a[j][1]))
                j--;
            else i++;
        }
        i=0;
        j=a.size()-1;
        while(i<j)
        {
            res=max(res,abs(c[i][0]-c[j][0])+abs(c[i][1]-c[j][1]));
            if(abs(c[i][1]-c[j-1][1])>abs(c[i][1]-c[j][1]))
                j--;
            else i++;
        }
        return res;
    }
};

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈乐乐happy

觉得对你有用的话可以打赏打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值