You are given a set of points in the 2D plane, represented as a list of points
where each point is a pair [x, y]
of integers. Your task is to find the minimum area of a rectangle formed by any four of these points, where the sides of the rectangle are parallel to the x and y axes. Each rectangle must have its four corners among the given points. If no such rectangle can be formed, return 0
.
0
if there are no valid rectangles.The brute-force way would be to check every quadruple of points to see if they form a rectangle, but this is highly inefficient as the number of quadruples grows rapidly with the number of points. Instead, we can look for patterns: for rectangles aligned with the axes, their sides are parallel to the axes, which means the rectangle is defined by two distinct x-values and two distinct y-values. If we can find two pairs of points that share the same x or y coordinates, we can check whether the other two corners exist.
The key insight is: for any pair of points that are diagonally opposite corners of a rectangle, if the other two required corners exist in the set, then a rectangle is formed. To make lookups fast, we can use a set to store all points for constant-time existence checks.
Instead of checking all quadruples, we can iterate over all pairs of points and, for each diagonal pair, check whether the other two corners exist. This brings the complexity down significantly, especially with the help of a set for quick lookups.
(x1, y1)
and (x2, y2)
:
x1 != x2
and y1 != y2
, ensuring they are diagonally opposite corners.(x1, y2)
and (x2, y1)
exist in the set.abs(x1 - x2) * abs(y1 - y2)
.x1 < x2
and y1 < y2
).Using a set for point existence checks is crucial for efficiency, reducing the time to check the presence of a point from O(n) to O(1).
Sample Input: points = [[1,1],[1,3],[3,1],[3,3],[2,2]]
(1,1)
and (3,3)
(diagonal corners).
(1,3)
and (3,1)
exist in the set. They do.abs(1-3) * abs(1-3) = 2 * 2 = 4
.(1,1)
and (2,2)
, but the other required corners do not exist.The optimized solution is much faster and feasible for the typical input constraints of this problem.
The key to solving the Minimum Area Rectangle problem efficiently is recognizing that rectangles aligned with the axes can be detected by checking pairs of diagonal corners and confirming the presence of the other two corners. By leveraging a set for constant-time lookups and iterating over all pairs, we reduce the complexity from O(n4) to O(n2). This approach is both elegant and practical, making it suitable for real-world inputs.
class Solution:
def minAreaRect(self, points):
point_set = set((x, y) for x, y in points)
min_area = float('inf')
n = len(points)
for i in range(n):
x1, y1 = points[i]
for j in range(i+1, n):
x2, y2 = points[j]
# Check for diagonal (not on same row or column)
if x1 != x2 and y1 != y2:
if (x1, y2) in point_set and (x2, y1) in point_set:
area = abs(x1 - x2) * abs(y1 - y2)
if area < min_area:
min_area = area
return 0 if min_area == float('inf') else min_area
class Solution {
public:
int minAreaRect(vector<vector<int>>& points) {
set<pair<int, int>> pointSet;
for (auto& p : points) {
pointSet.insert({p[0], p[1]});
}
int minArea = INT_MAX;
int n = points.size();
for (int i = 0; i < n; ++i) {
int x1 = points[i][0], y1 = points[i][1];
for (int j = i + 1; j < n; ++j) {
int x2 = points[j][0], y2 = points[j][1];
if (x1 != x2 && y1 != y2) {
if (pointSet.count({x1, y2}) && pointSet.count({x2, y1})) {
int area = abs(x1 - x2) * abs(y1 - y2);
if (area < minArea) minArea = area;
}
}
}
}
return minArea == INT_MAX ? 0 : minArea;
}
};
import java.util.*;
class Solution {
public int minAreaRect(int[][] points) {
Set<String> pointSet = new HashSet<>();
for (int[] p : points) {
pointSet.add(p[0] + "," + p[1]);
}
int minArea = Integer.MAX_VALUE;
int n = points.length;
for (int i = 0; i < n; ++i) {
int x1 = points[i][0], y1 = points[i][1];
for (int j = i + 1; j < n; ++j) {
int x2 = points[j][0], y2 = points[j][1];
if (x1 != x2 && y1 != y2) {
if (pointSet.contains(x1 + "," + y2) && pointSet.contains(x2 + "," + y1)) {
int area = Math.abs(x1 - x2) * Math.abs(y1 - y2);
if (area < minArea) minArea = area;
}
}
}
}
return minArea == Integer.MAX_VALUE ? 0 : minArea;
}
}
var minAreaRect = function(points) {
const pointSet = new Set(points.map(p => p[0] + ',' + p[1]));
let minArea = Infinity;
const n = points.length;
for (let i = 0; i < n; ++i) {
let [x1, y1] = points[i];
for (let j = i + 1; j < n; ++j) {
let [x2, y2] = points[j];
if (x1 !== x2 && y1 !== y2) {
if (pointSet.has(x1 + ',' + y2) && pointSet.has(x2 + ',' + y1)) {
let area = Math.abs(x1 - x2) * Math.abs(y1 - y2);
if (area < minArea) minArea = area;
}
}
}
}
return minArea === Infinity ? 0 : minArea;
};