Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

598. Range Addition II - Leetcode Solution

Problem Description

You are given an m x n matrix initialized with all 0's, and a list of ops, where ops[i] = [a, b] means that for each operation, you increment every element in the rectangle defined by its top-left corner (0, 0) and bottom-right corner (a-1, b-1) by 1.

After performing all the operations, your task is to find how many elements in the matrix have the maximum integer value.

  • Each operation is described by two integers a and b, both greater than 0 and less than or equal to m and n respectively.
  • Constraints ensure that the size of ops can be zero, in which case the entire matrix remains zero.
  • All increments are cumulative, and the order of operations does not affect the final answer.

Thought Process

At first glance, you might consider simulating each operation on the matrix: for each ops[i], increment every cell in the submatrix defined by [0, 0] to [a-1, b-1]. However, this brute-force approach is inefficient, especially for large matrices and many operations.

Instead, let's think about what the problem is really asking. Each operation increases the count in a rectangle, and the cells that get incremented in every operation are those that are inside the overlap of all rectangles. The cell(s) that are incremented the most times (i.e., have the maximum value) are those that are inside all rectangles.

So, the problem reduces to finding the intersection of all rectangles defined by the operations, and counting how many elements are in that intersection.

Solution Approach

  • Step 1: If there are no operations, then no cell is incremented and the entire matrix has the same value (0). In this case, every cell has the maximum value, so the answer is m * n.
  • Step 2: For each operation [a, b], the incremented area is from (0, 0) to (a-1, b-1). The intersection of all these rectangles is the rectangle from (0, 0) to (min_a-1, min_b-1), where min_a is the minimum a among all operations and min_b is the minimum b.
  • Step 3: The area of the intersection rectangle is min_a * min_b. This gives the number of cells that have been incremented in every operation, and thus have the maximum value.
  • Step 4: Return min_a * min_b as the answer.

This approach is efficient because it only requires a single pass through the ops list to find the minimum a and b values.

Example Walkthrough

Example Input:
m = 3, n = 3, ops = [[2,2],[3,3]]

  1. The first operation increments the submatrix from (0,0) to (1,1) (a 2x2 area).
  2. The second operation increments the submatrix from (0,0) to (2,2) (a 3x3 area).
  3. The intersection of these two is the 2x2 area from (0,0) to (1,1).
  4. Therefore, 4 cells (2x2) have the maximum value (which is 2, since they were incremented twice).
  5. All other cells were incremented only once (by the second operation).

Output: 4

Time and Space Complexity

  • Brute-force approach: For each operation, increment all elements in the given rectangle. For k operations, each possibly covering up to m * n cells, the time complexity is O(k * m * n). The space complexity is O(m * n) for the matrix.
  • Optimized approach: We only need to find the minimum a and b among all operations, which takes O(k) time and O(1) space. No need to allocate the matrix.

Summary

The key insight is to realize that the cells with the maximum value are those that are covered by all operations, i.e., the intersection of all rectangles. By simply finding the minimum a and b among all operations, we can directly compute the answer in linear time without simulating the matrix updates. This leads to an elegant and efficient solution.

Code Implementation

class Solution:
    def maxCount(self, m: int, n: int, ops: List[List[int]]) -> int:
        if not ops:
            return m * n
        min_a = min(op[0] for op in ops)
        min_b = min(op[1] for op in ops)
        return min_a * min_b
      
class Solution {
public:
    int maxCount(int m, int n, vector<vector<int>>& ops) {
        if (ops.empty()) return m * n;
        int min_a = m, min_b = n;
        for (const auto& op : ops) {
            min_a = min(min_a, op[0]);
            min_b = min(min_b, op[1]);
        }
        return min_a * min_b;
    }
};
      
class Solution {
    public int maxCount(int m, int n, int[][] ops) {
        if (ops.length == 0) return m * n;
        int minA = m, minB = n;
        for (int[] op : ops) {
            minA = Math.min(minA, op[0]);
            minB = Math.min(minB, op[1]);
        }
        return minA * minB;
    }
}
      
var maxCount = function(m, n, ops) {
    if (ops.length === 0) return m * n;
    let minA = m, minB = n;
    for (let i = 0; i < ops.length; i++) {
        minA = Math.min(minA, ops[i][0]);
        minB = Math.min(minB, ops[i][1]);
    }
    return minA * minB;
};