【1499. 满足不等式的最大值】

文章介绍了如何解决LeetCode上的一道题目,涉及在给定数组points和整数k的情况下,找到满足yi+yj+|xi-xj|≤k的最大值的问题。提出了两种方法,一种使用最小堆,另一种使用双端队列,分别分析了它们的时间和空间复杂度。
摘要由CSDN通过智能技术生成

来源:力扣(LeetCode)

描述:

给你一个数组 points 和一个整数 k 。数组中每个元素都表示二维平面上的点的坐标,并按照横坐标 x 的值从小到大排序。也就是说 points[i] = [xi, yi] ,并且在 1 <= i < j <= points.length 的前提下, xi < xj 总成立。

请你找出 yi + yj + |xi - xj|最大值,其中 |xi - xj| <= k1 <= i < j <= points.length

题目测试数据保证至少存在一对能够满足 |xi - xj| <= k 的点。

示例 1:

输入:points = [[1,3],[2,0],[5,10],[6,-10]], k = 1
输出:4
解释:前两个点满足 |xi - xj| <= 1 ,代入方程计算,则得到值 3 + 0 + |1 - 2| = 4 。第三个和第四个点也满足条件,得到值 10 + -10 + |5 - 6| = 1 。
没有其他满足条件的点,所以返回 41 中最大的那个。

示例 2:

输入:points = [[0,0],[3,0],[9,2]], k = 3
输出:3
解释:只有前两个点满足 |xi - xj| <= 3 ,代入方程后得到值 0 + 0 + |0 - 3| = 3

提示:

  • 2 <= points.length <= 105
  • points[i].length == 2
  • -108 <= points[i][0], points[i][1] <= 108
  • 0 <= k <= 2 * 108
  • 对于所有的1 <= i < j <= points.length ,points[i][0] < points[j][0] 都成立。也就是说,xi 是严格递增的。

方法一:堆

思路

题目要求 yi + yj + ∣xi − xj∣,其中 ∣xi − xj∣ ≤ k 的最大值。根据题目条件,i < j 时,xi < xj,可以拆去绝对值符号,得到
(−xi + yi) + (xj + yj),其中 xj − xi ≤ k。

根据这个等式,可以遍历 points 所有点,使每个点作为 [xj, yj] ,并且求出满足 xj − xi ≤ k 的最大的 (−xi + yi),而这一步,可以用堆来完成。用一个最小堆,堆的元素是 [x − y, x],堆顶元素的 (x − y) 值最小,即 (−x + y) 值最大。每次遍历一个点时,先弹出堆顶不满足当前 xj − xi ≤ k 的元素,然后用堆顶元素和当前元素计算 (−xi + yi) + (xj + yj),再将当前元素放入堆。遍历完后,即得到了式子的最大值。

代码:

class Solution {
public:
    using pii = pair<int, int>;
    int findMaxValueOfEquation(vector<vector<int>>& points, int k) {
        int res = INT_MIN;
        priority_queue<pii, vector<pii>, greater<pii>> heap;
        for (auto &point : points) {
            int x = point[0], y = point[1];
            while (!heap.empty() && x - heap.top().second > k) {
                heap.pop();
            }
            if (!heap.empty()) {
                res = max(res, x + y - heap.top().first);
            }
            heap.emplace(x - y, x);
        }
        return res;
    }
};

执行用时:236 ms, 在所有 C++ 提交中击败了87.91%的用户
内存消耗:90 MB, 在所有 C++ 提交中击败了45.05%的用户
复杂度分析
时间复杂度:O(n×logn),其中 n 是 points 的长度,每个元素最多进入并离开 heap 一次。
空间复杂度:O(n),是 heap 的空间复杂度。

方法二:双端队列

思路

与方法一思路类似,方法一用堆来求满足 xj − xi ≤ k 的最大的 (−xi + yi),而这一步可以用双端队列来求,从而降低时间复杂度。使用一个双端队列 q,元素为 [y − x, x]。每次遍历一个点时,首先同样要弹出队列头部不满足 xj − xi ≤ k 的元素,然后用队列头部元素和当前元素计算 (yi − xi) + (xj + yj)。在当前元素进入队列尾端时,需要弹出队列末端小于等于当前 yj − xj 的元素,这样以来,可以使得双端队列保持递减,从而头部元素最大。然后将当前元素压入队列末端。遍历完后,即得到了式子的最大值。

代码:

class Solution {
public:
    using pii = pair<int, int>;
    int findMaxValueOfEquation(vector<vector<int>>& points, int k) {
        int res = INT_MIN;
        deque<pii> qu;
        for (auto &point : points) {
            int x = point[0], y = point[1];
            while (!qu.empty() && x - qu.front().second > k) {
                qu.pop_front();
            }
            if (!qu.empty()) {
                res = max(res, x + y + qu.front().first);
            }
            while (!qu.empty() && y - x >= qu.back().first) {
                qu.pop_back();
            }
            qu.emplace_back(y - x, x);
        }
        return res;
    }
};

执行用时:244ms, 在所有 C++ 提交中击败了73.63%的用户
内存消耗:88.9 MB, 在所有 C++ 提交中击败了63.74%的用户
复杂度分析
时间复杂度:O(n),其中 n 是 points 的长度,每个元素最多进入并离开 q 一次。
空间复杂度:O(n),是 q 的空间复杂度。
author:LeetCode-Solution

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

千北@

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值