Skip to content

391. Perfect Rectangle

Description

Given an array rectangles where rectangles[i] = [xi, yi, ai, bi] represents an axis-aligned rectangle. The bottom-left point of the rectangle is (xi, yi) and the top-right point of it is (ai, bi).

Return true if all the rectangles together form an exact cover of a rectangular region.

 

Example 1:

Input: rectangles = [[1,1,3,3],[3,1,4,2],[3,2,4,4],[1,3,2,4],[2,3,3,4]]
Output: true
Explanation: All 5 rectangles together form an exact cover of a rectangular region.

Example 2:

Input: rectangles = [[1,1,2,3],[1,3,2,4],[3,1,4,2],[3,2,4,4]]
Output: false
Explanation: Because there is a gap between the two rectangular regions.

Example 3:

Input: rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[2,2,4,4]]
Output: false
Explanation: Because two of the rectangles overlap with each other.

 

Constraints:

  • 1 <= rectangles.length <= 2 * 104
  • rectangles[i].length == 4
  • -105 <= xi, yi, ai, bi <= 105

 

Solutions

Solution: Greedy

  • Time complexity: O(n)
  • Space complexity: O(n)

 

JavaScript

js
/**
 * @param {number[][]} rectangles
 * @return {boolean}
 */
const isRectangleCover = function (rectangles) {
  const pointSet = new Set();
  let minX = (minY = Number.MAX_SAFE_INTEGER);
  let maxX = (maxY = Number.MIN_SAFE_INTEGER);
  let area = 0;

  for (const [x1, y1, x2, y2] of rectangles) {
    const point1 = `${x1}_${y1}`;
    const point2 = `${x1}_${y2}`;
    const point3 = `${x2}_${y1}`;
    const point4 = `${x2}_${y2}`;

    minX = Math.min(x1, minX);
    minY = Math.min(y1, minY);
    maxX = Math.max(x2, maxX);
    maxY = Math.max(y2, maxY);
    area += (x2 - x1) * (y2 - y1);
    pointSet.has(point1) ? pointSet.delete(point1) : pointSet.add(point1);
    pointSet.has(point2) ? pointSet.delete(point2) : pointSet.add(point2);
    pointSet.has(point3) ? pointSet.delete(point3) : pointSet.add(point3);
    pointSet.has(point4) ? pointSet.delete(point4) : pointSet.add(point4);
  }
  if (pointSet.size !== 4) return false;
  if (!pointSet.has(`${minX}_${minY}`)) return false;
  if (!pointSet.has(`${minX}_${maxY}`)) return false;
  if (!pointSet.has(`${maxX}_${minY}`)) return false;
  if (!pointSet.has(`${maxX}_${maxY}`)) return false;

  return (maxX - minX) * (maxY - minY) === area;
};

Released under the MIT license