Max Value of Equation

hard monotonic deque sliding window

Problem

You get an array of 2-D points, points[i] = [xi, yi], sorted by strictly increasing x-coordinate, and an integer k. Over all pairs i < j with |xi − xj| ≤ k, return the maximum value of yi + yj + |xi − xj|. At least one valid pair is guaranteed.

Since the x's are sorted, for i < j the value equals (xj + yj) + (yi − xi). So while scanning, each new point only needs the largest yi − xi among earlier points within x-distance k — a sliding-window maximum, maintained by a monotonic decreasing deque.

Inputpoints = [[1,3],[2,0],[5,10],[6,-10]], k = 1
Output4
Pair (1,3) with (2,0): 3 + 0 + |1 − 2| = 4. The only other in-range pair, (5,10) with (6,−10), gives just 10 − 10 + 1 = 1.

def find_max_value_of_equation(points, k):
    dq = deque()                  # (x, y - x), front keeps the max
    best = float('-inf')
    for x, y in points:
        while dq and x - dq[0][0] > k:
            dq.popleft()          # window: too far left, expire
        if dq:
            best = max(best, x + y + dq[0][1])
        while dq and dq[-1][1] <= y - x:
            dq.pop()              # dominated by the new point
        dq.append((x, y - x))
    return best
function findMaxValueOfEquation(points, k) {
  const dq = [];                       // [x, y - x], front keeps the max
  let best = -Infinity;
  for (const [x, y] of points) {
    while (dq.length && x - dq[0][0] > k) {
      dq.shift();                      // window: too far left, expire
    }
    if (dq.length) {
      best = Math.max(best, x + y + dq[0][1]);
    }
    while (dq.length && dq[dq.length - 1][1] <= y - x) {
      dq.pop();                        // dominated by the new point
    }
    dq.push([x, y - x]);
  }
  return best;
}
public int findMaxValueOfEquation(int[][] points, int k) {
    Deque<int[]> dq = new ArrayDeque<>();  // {x, y - x}, front keeps the max
    int best = Integer.MIN_VALUE;
    for (int[] p : points) {
        int x = p[0], y = p[1];
        while (!dq.isEmpty() && x - dq.peekFirst()[0] > k) {
            dq.pollFirst();                 // window: too far left, expire
        }
        if (!dq.isEmpty()) {
            best = Math.max(best, x + y + dq.peekFirst()[1]);
        }
        while (!dq.isEmpty() && dq.peekLast()[1] <= y - x) {
            dq.pollLast();                  // dominated by the new point
        }
        dq.offerLast(new int[]{x, y - x});
    }
    return best;
}
int findMaxValueOfEquation(vector<vector<int>>& points, int k) {
    deque<pair<int,int>> dq;                // {x, y - x}, front keeps the max
    int best = INT_MIN;
    for (auto& p : points) {
        int x = p[0], y = p[1];
        while (!dq.empty() && x - dq.front().first > k) {
            dq.pop_front();                 // window: too far left, expire
        }
        if (!dq.empty()) {
            best = max(best, x + y + dq.front().second);
        }
        while (!dq.empty() && dq.back().second <= y - x) {
            dq.pop_back();                  // dominated by the new point
        }
        dq.push_back({x, y - x});
    }
    return best;
}
Time: O(n) Space: O(n)