【力扣每日一题】2023.7.21 满足不等式的最大值

目录

题目:

示例:

分析:

代码+运行结果:


题目:

示例:

分析:

给我们一堆按照x轴从小到大排序的坐标,让我们找出满足条件的两个坐标经过一个式子计算得到的最大值.

首先,条件是两个坐标的x轴之差的绝对值小于等于k.

然后式子为

yi+yj+|xi-xj|  (i<j)

我们可以很容易就看出来,由于i<j,而坐标又是按照x轴从小到大的顺序排列的,因此 |xi-xj| 可以改成不加绝对值的 xj-xi ,然后整个式子就变成了 yi+yj+xj-xi ,我们再变换一下 (yj+xj)+(yi-xi) .

那么就可以知道公式得出的值就等于比较后面的坐标的xy之和再加上比较前面的坐标的yx之差,并且两个坐标的x轴上的差不能大于k,

由于需要维护两个坐标的x轴的差,因此我们可以使用栈或队列来做.

我一开始用的是栈,然后发现是做不成的,因为虽然x轴的坐标是排序后的,但是y轴的值可是参差不齐,直接使用栈的话会遗漏一些符合条件的坐标对.

所以我们可以使用队列来做,并且是双端队列.

第一是要维护队列开头的坐标的x轴与最新坐标的x轴的差不能大于k.

第二需要维护队列末尾自身y轴与x轴的差要大于最新坐标的y轴与x轴的差,根据上面推导后的公式 (yj+xj)+(yi-xi) 我们可以得知,公式得出的值和两个参数有关.

一个是新(x轴更大)坐标的x轴y轴之和.

另一个是老(x轴更小,存在队列末尾处的)坐标的y轴和x轴的差.

第一个我们无法决定,但是第二个我们是可以更新,如果一个新来的坐标的第二个参数的值比队列末尾的第二参数的值更大,我们可以果断抛弃队列末尾的那个坐标,因为如果更后面来的坐标可以匹配此时队列末尾的坐标,那么就更可以匹配新来的坐标了,因为越后面来的坐标x轴越大,而新来的坐标比队列末尾的坐标可以提供更大的值,因此当新坐标的y轴与x轴的差比队列末尾的y与x之差更大时,可以抛弃队列末尾的坐标.

可以参考下面的动图以及代码来理解理解.

动图比较大,下面是拆分以后的动图:

 

 

代码+运行结果:

class Solution {
public:
    int findMaxValueOfEquation(vector<vector<int>>& points, int k) {
        int res=INT_MIN;
        deque<vector<int>>d;
        for(const auto &point:points){
            //如果队列不为空,并且此时的坐标x轴-队列开头的x轴>k,那么可以把队列开头丢掉
            //因为后面的坐标都比此时坐标大,就不会有和队列开头的坐标满足不等式的坐标了
            //因为不确定要丢几个,因此需要使用while
            while(!d.empty() && point[0]-d.front()[0]>k){
                d.pop_front();
            }
            
            //如果队列不为空,那么可以更新res
            if(!d.empty()){
                res=max(res,point[0]-d.front()[0]+point[1]+d.front()[1]);
            }

            //如果队列不为空,并且队列的末尾y轴与x轴的差小于等于此时坐标的y轴x轴的差,那么抛弃队列末尾.
            //因为xj一定比xi大,因此|xi-xj|可以改成xj-xi,题中的式子就变成了(yi-xi)+(yj+xj)
            //式子的值和老坐标y轴与x轴的差有关,所以如果发现此时的坐标的yx之差比队列末尾的yx之差更大
            //就可以将队列末尾丢弃,如果更后面的坐标可以和此时队列末尾的坐标匹配,那么也就可以和此时的坐标匹配
            //而此时的坐标可以贡献更大的值,为了避免不必要的计算,可以将队列末尾贡献更小的坐标丢弃.
            while(!d.empty()&&d.back()[1]-d.back()[0]<=point[1]-point[0]){
                d.pop_back();
            }
            d.push_back(point);
        }
        return res;
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值