3380. Maximum Area Rectangle With Point Constraints I
Problem Description
You are given a set of points on a 2D plane, where each point is represented as [x, y]
coordinates. Your goal is to find the largest possible rectangle that can be formed using exactly four of these points as corners, with some specific constraints.
The rectangle must satisfy three conditions:
-
Use exactly four points as corners: The rectangle's four corners must be points from the given array.
-
No other points inside or on the boundary: Apart from the four corner points, no other point from the array can be located inside the rectangle or on its edges. The rectangle must be "empty" except for its corners.
-
Axis-aligned edges: The rectangle's sides must be parallel to the x-axis and y-axis (not rotated at an angle).
If such a rectangle exists, return its maximum possible area. If no valid rectangle can be formed following these rules, return -1.
For example, if you have points that can form multiple valid rectangles, you want the one with the largest area. The area is calculated as width × height
where width is the difference in x-coordinates and height is the difference in y-coordinates.
Intuition
Since we need to find axis-aligned rectangles, any valid rectangle can be uniquely defined by two opposite corners - specifically, the bottom-left corner and the top-right corner. This is because once we know these two corners, the other two corners are automatically determined (bottom-right and top-left).
The key insight is that we can try all possible pairs of points from our array and treat them as potential opposite corners of a rectangle. For each pair of points (x1, y1)
and (x2, y2)
, we can determine:
- The bottom-left corner would be at
(min(x1, x2), min(y1, y2))
- The top-right corner would be at
(max(x1, x2), max(y1, y2))
Once we have these potential rectangle boundaries, we need to verify if this forms a valid rectangle according to our constraints. We check every point in the array:
- If a point is outside the rectangle boundaries, we ignore it
- If a point is exactly at one of the four corners, we count it
- If a point is inside the rectangle or on its edges (but not a corner), this rectangle is invalid
A valid rectangle must have exactly 4 points at its corners and no other points inside or on its boundaries.
The brute force approach works here because we're checking all O(n²)
pairs of points as potential opposite corners, and for each pair, we verify all n
points to check validity. This gives us O(n³)
time complexity, which is acceptable for typical constraint sizes.
The area calculation is straightforward: (x_max - x_min) × (y_max - y_min)
. We keep track of the maximum area found among all valid rectangles.
Learn more about Segment Tree, Math and Sorting patterns.
Solution Approach
The solution implements the enumeration strategy by trying all possible pairs of points as potential opposite corners of a rectangle.
Main Algorithm Structure:
-
Enumerate all pairs of points: The outer loop iterates through each point
(x1, y1)
with indexi
, and the inner loop iterates through all previous points(x2, y2)
with indices less thani
. This ensures we check each pair exactly once. -
Determine rectangle boundaries: For each pair of points, calculate the actual rectangle corners:
- Bottom-left corner:
(x3, y3) = (min(x1, x2), min(y1, y2))
- Top-right corner:
(x4, y4) = (max(x1, x2), max(y1, y2))
- Bottom-left corner:
-
Validation function
check(x1, y1, x2, y2)
: This helper function verifies if the rectangle defined by bottom-left(x1, y1)
and top-right(x2, y2)
is valid:- Initialize a counter
cnt = 0
to track corner points - For each point
(x, y)
in the array:- If the point is outside the rectangle (
x < x1
orx > x2
ory < y1
ory > y2
), skip it - If the point is at a corner (both
x
equals eitherx1
orx2
ANDy
equals eithery1
ory2
), increment the counter - If the point is inside or on the edge but not a corner, return
False
immediately
- If the point is outside the rectangle (
- Return
True
if exactly 4 corner points were found
- Initialize a counter
-
Area calculation and tracking: If the rectangle is valid:
- Calculate area as
(x4 - x3) * (y4 - y3)
- Update the maximum area using
ans = max(ans, area)
- Calculate area as
-
Return result: Return the maximum area found, or -1 if no valid rectangle exists (initial value).
Key Implementation Details:
- The use of
points[:i]
in the inner loop ensures we only check each pair once, avoiding duplicate calculations - The early return in the
check
function (return False
) immediately invalidates a rectangle if any non-corner point is found within its boundaries - The condition
(x == x1 or x == x2) and (y == y1 or y == y2)
precisely identifies corner points - The algorithm correctly handles the case where the two enumerated points form a diagonal (most common) or are on the same edge of the rectangle
This approach guarantees finding the maximum area rectangle if one exists, as it exhaustively checks all possible rectangle configurations defined by pairs of points.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with a concrete example. Suppose we have the following points:
points = [[1,1], [1,3], [3,1], [3,3], [2,2]]
Step 1: Visualize the points
3 | · · 2 | · 1 | · · +---------- 1 2 3
Step 2: Try pairs as potential opposite corners
Let's trace through a few iterations:
Iteration 1: Consider points [1,1] and [1,3]
- Rectangle boundaries: bottom-left = (1,1), top-right = (1,3)
- This forms a line (width = 0), area = 0
- Check validation: We need 4 corners, but we only have 2 points on this line
- Invalid rectangle
Iteration 2: Consider points [1,1] and [3,1]
- Rectangle boundaries: bottom-left = (1,1), top-right = (3,1)
- This forms a line (height = 0), area = 0
- Invalid rectangle (same reason)
Iteration 3: Consider points [1,1] and [3,3]
- Rectangle boundaries: bottom-left = (1,1), top-right = (3,3)
- Rectangle corners should be: (1,1), (1,3), (3,1), (3,3)
- Area = (3-1) × (3-1) = 4
Validation for this rectangle:
- Check point [1,1]: At corner ✓ (x=1 matches x_min, y=1 matches y_min)
- Check point [1,3]: At corner ✓ (x=1 matches x_min, y=3 matches y_max)
- Check point [3,1]: At corner ✓ (x=3 matches x_max, y=1 matches y_min)
- Check point [3,3]: At corner ✓ (x=3 matches x_max, y=3 matches y_max)
- Check point [2,2]: Inside rectangle but NOT at corner ✗
- x=2 is between 1 and 3 (not at boundary x=1 or x=3)
- y=2 is between 1 and 3 (not at boundary y=1 or y=3)
- This invalidates the rectangle!
Continue with other pairs...
Now let's modify the example to have a valid rectangle:
points = [[1,1], [1,3], [3,1], [3,3], [4,2]]
Checking [1,1] and [3,3] again:
- Rectangle boundaries: bottom-left = (1,1), top-right = (3,3)
- Validation:
- [1,1]: At corner ✓ (cnt = 1)
- [1,3]: At corner ✓ (cnt = 2)
- [3,1]: At corner ✓ (cnt = 3)
- [3,3]: At corner ✓ (cnt = 4)
- [4,2]: Outside rectangle (x=4 > x_max=3), skip
- Result: cnt = 4, rectangle is valid!
- Area = 2 × 2 = 4
The algorithm continues checking all other pairs, but this would be the maximum area rectangle found, so the function returns 4.
Solution Implementation
1class Solution:
2 def maxRectangleArea(self, points: List[List[int]]) -> int:
3 def is_valid_rectangle(min_x: int, min_y: int, max_x: int, max_y: int) -> bool:
4 """
5 Check if the given bounds form a valid rectangle with exactly 4 corner points
6 and no other points inside or on the edges.
7
8 Args:
9 min_x, min_y: Bottom-left corner coordinates
10 max_x, max_y: Top-right corner coordinates
11
12 Returns:
13 True if valid rectangle, False otherwise
14 """
15 corner_count = 0
16
17 for x, y in points:
18 # Skip points outside the rectangle bounds
19 if x < min_x or x > max_x or y < min_y or y > max_y:
20 continue
21
22 # Check if point is at a corner
23 if (x == min_x or x == max_x) and (y == min_y or y == max_y):
24 corner_count += 1
25 continue
26
27 # Point is inside or on edge but not at corner - invalid rectangle
28 return False
29
30 # Valid rectangle must have exactly 4 corners
31 return corner_count == 4
32
33 max_area = -1
34
35 # Try all pairs of points as potential diagonal corners
36 for i, (x1, y1) in enumerate(points):
37 for x2, y2 in points[:i]:
38 # Calculate rectangle bounds from two points
39 left = min(x1, x2)
40 bottom = min(y1, y2)
41 right = max(x1, x2)
42 top = max(y1, y2)
43
44 # Check if these bounds form a valid rectangle
45 if is_valid_rectangle(left, bottom, right, top):
46 area = (right - left) * (top - bottom)
47 max_area = max(max_area, area)
48
49 return max_area
50
1class Solution {
2 /**
3 * Finds the maximum area of a rectangle formed by exactly 4 points from the given array.
4 * The rectangle must be axis-aligned and contain no other points inside or on its edges
5 * except for the 4 corner points.
6 *
7 * @param points 2D array where each element represents a point [x, y]
8 * @return Maximum rectangle area, or -1 if no valid rectangle exists
9 */
10 public int maxRectangleArea(int[][] points) {
11 int maxArea = -1;
12
13 // Try all pairs of points as potential diagonal corners of a rectangle
14 for (int i = 0; i < points.length; ++i) {
15 int firstPointX = points[i][0];
16 int firstPointY = points[i][1];
17
18 for (int j = 0; j < i; ++j) {
19 int secondPointX = points[j][0];
20 int secondPointY = points[j][1];
21
22 // Calculate the bounding box coordinates
23 // Bottom-left corner (minimum x and y)
24 int leftX = Math.min(firstPointX, secondPointX);
25 int bottomY = Math.min(firstPointY, secondPointY);
26
27 // Top-right corner (maximum x and y)
28 int rightX = Math.max(firstPointX, secondPointX);
29 int topY = Math.max(firstPointY, secondPointY);
30
31 // Verify if these coordinates form a valid rectangle
32 if (isValidRectangle(points, leftX, bottomY, rightX, topY)) {
33 int currentArea = (rightX - leftX) * (topY - bottomY);
34 maxArea = Math.max(maxArea, currentArea);
35 }
36 }
37 }
38
39 return maxArea;
40 }
41
42 /**
43 * Checks if the given rectangle bounds form a valid rectangle with exactly 4 corner points
44 * and no other points inside or on the edges.
45 *
46 * @param points Array of all points to check
47 * @param leftX Left boundary x-coordinate
48 * @param bottomY Bottom boundary y-coordinate
49 * @param rightX Right boundary x-coordinate
50 * @param topY Top boundary y-coordinate
51 * @return true if valid rectangle with exactly 4 corners, false otherwise
52 */
53 private boolean isValidRectangle(int[][] points, int leftX, int bottomY,
54 int rightX, int topY) {
55 int cornerCount = 0;
56
57 for (int[] point : points) {
58 int currentX = point[0];
59 int currentY = point[1];
60
61 // Skip points outside the rectangle bounds
62 if (currentX < leftX || currentX > rightX ||
63 currentY < bottomY || currentY > topY) {
64 continue;
65 }
66
67 // Check if point is at a corner
68 boolean isAtVerticalEdge = (currentX == leftX || currentX == rightX);
69 boolean isAtHorizontalEdge = (currentY == bottomY || currentY == topY);
70
71 if (isAtVerticalEdge && isAtHorizontalEdge) {
72 // Point is at a corner
73 cornerCount++;
74 continue;
75 }
76
77 // Point is inside or on edge but not at corner - invalid rectangle
78 return false;
79 }
80
81 // Valid rectangle must have exactly 4 corners
82 return cornerCount == 4;
83 }
84}
85
1class Solution {
2public:
3 int maxRectangleArea(vector<vector<int>>& points) {
4 // Lambda function to check if the given rectangle bounds form a valid rectangle
5 // with exactly 4 corner points and no interior/edge points
6 auto isValidRectangle = [&](int minX, int minY, int maxX, int maxY) -> bool {
7 int cornerCount = 0;
8
9 // Check each point in the input array
10 for (const auto& point : points) {
11 int currentX = point[0];
12 int currentY = point[1];
13
14 // Skip points outside the rectangle bounds
15 if (currentX < minX || currentX > maxX || currentY < minY || currentY > maxY) {
16 continue;
17 }
18
19 // Check if point is at a corner of the rectangle
20 if ((currentX == minX || currentX == maxX) && (currentY == minY || currentY == maxY)) {
21 cornerCount++;
22 continue;
23 }
24
25 // Point is inside rectangle or on edge but not at corner - invalid rectangle
26 return false;
27 }
28
29 // Valid rectangle must have exactly 4 corner points
30 return cornerCount == 4;
31 };
32
33 int maxArea = -1;
34
35 // Try all pairs of points as potential opposite corners of a rectangle
36 for (int i = 0; i < points.size(); i++) {
37 int x1 = points[i][0];
38 int y1 = points[i][1];
39
40 for (int j = 0; j < i; j++) {
41 int x2 = points[j][0];
42 int y2 = points[j][1];
43
44 // Calculate rectangle bounds using the two points
45 int leftBound = min(x1, x2);
46 int bottomBound = min(y1, y2);
47 int rightBound = max(x1, x2);
48 int topBound = max(y1, y2);
49
50 // Check if these bounds form a valid rectangle
51 if (isValidRectangle(leftBound, bottomBound, rightBound, topBound)) {
52 // Calculate area and update maximum
53 int area = (rightBound - leftBound) * (topBound - bottomBound);
54 maxArea = max(maxArea, area);
55 }
56 }
57 }
58
59 return maxArea;
60 }
61};
62
1/**
2 * Finds the maximum area of a rectangle that can be formed by points
3 * where all four corners must be from the given points and no other points
4 * can be inside or on the edges of the rectangle
5 * @param points - Array of points where each point is [x, y]
6 * @returns Maximum rectangle area, or -1 if no valid rectangle exists
7 */
8function maxRectangleArea(points: number[][]): number {
9 /**
10 * Checks if a rectangle defined by bottom-left (x1, y1) and top-right (x2, y2)
11 * is valid (has exactly 4 corner points from the input and no other points inside/on edges)
12 * @param x1 - Left x-coordinate of rectangle
13 * @param y1 - Bottom y-coordinate of rectangle
14 * @param x2 - Right x-coordinate of rectangle
15 * @param y2 - Top y-coordinate of rectangle
16 * @returns True if the rectangle is valid, false otherwise
17 */
18 const isValidRectangle = (x1: number, y1: number, x2: number, y2: number): boolean => {
19 let cornerCount = 0;
20
21 // Check each point to see if it's inside, on corners, or outside the rectangle
22 for (const point of points) {
23 const [x, y] = point;
24
25 // Skip points outside the rectangle bounds
26 if (x < x1 || x > x2 || y < y1 || y > y2) {
27 continue;
28 }
29
30 // Check if point is at one of the four corners
31 if ((x === x1 || x === x2) && (y === y1 || y === y2)) {
32 cornerCount++;
33 continue;
34 }
35
36 // Point is inside or on edge but not a corner - invalid rectangle
37 return false;
38 }
39
40 // Valid rectangle must have exactly 4 corner points
41 return cornerCount === 4;
42 };
43
44 let maxArea = -1;
45
46 // Try all pairs of points as potential opposite corners of a rectangle
47 for (let i = 0; i < points.length; i++) {
48 const [x1, y1] = points[i];
49
50 for (let j = 0; j < i; j++) {
51 const [x2, y2] = points[j];
52
53 // Calculate rectangle bounds (bottom-left and top-right corners)
54 const minX = Math.min(x1, x2);
55 const minY = Math.min(y1, y2);
56 const maxX = Math.max(x1, x2);
57 const maxY = Math.max(y1, y2);
58
59 // Check if this forms a valid rectangle and update max area
60 if (isValidRectangle(minX, minY, maxX, maxY)) {
61 const area = (maxX - minX) * (maxY - minY);
62 maxArea = Math.max(maxArea, area);
63 }
64 }
65 }
66
67 return maxArea;
68}
69
Time and Space Complexity
The time complexity of this algorithm is O(n^3)
, where n
is the length of the array points
.
This complexity arises from:
- The nested loops in the main function iterate through all pairs of points, which takes
O(n^2)
time - For each pair of points, the
check
function is called, which iterates through alln
points once to verify if they form a valid rectangle - Therefore, the total time complexity is
O(n^2) × O(n) = O(n^3)
The space complexity is O(1)
as the algorithm only uses a constant amount of extra space regardless of the input size. The variables ans
, cnt
, x1
, y1
, x2
, y2
, x3
, y3
, x4
, and y4
are all primitive types that don't scale with the input size.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Corner Detection Logic
One of the most common mistakes is incorrectly identifying corner points. Developers often write conditions like:
# WRONG: This uses OR instead of AND if (x == min_x or x == max_x) or (y == min_y or y == max_y): corner_count += 1
This would incorrectly count points that are on the edges but not at corners. For example, a point at (min_x, (min_y + max_y)/2)
would be counted as a corner.
Solution: Use AND to ensure the point is at both a boundary x-coordinate AND a boundary y-coordinate:
# CORRECT if (x == min_x or x == max_x) and (y == min_y or y == max_y): corner_count += 1
2. Missing Edge Case: Degenerate Rectangles
The code might not handle cases where the two selected points have the same x or y coordinate, forming a line rather than a rectangle:
# This creates a "rectangle" with zero area
left = min(x1, x2) # Could equal right if x1 == x2
right = max(x1, x2)
Solution: Add a check to skip degenerate cases:
# Skip if points form a line (zero area) if x1 == x2 or y1 == y2: continue
3. Floating Point Coordinates
If the problem allows floating-point coordinates, direct equality comparisons become unreliable due to precision issues:
# Problematic with floating-point values if x == min_x or x == max_x: # May fail due to precision
Solution: Use an epsilon value for floating-point comparisons:
EPSILON = 1e-9
def is_at_boundary(val, boundary1, boundary2):
return abs(val - boundary1) < EPSILON or abs(val - boundary2) < EPSILON
# Use in validation
if is_at_boundary(x, min_x, max_x) and is_at_boundary(y, min_y, max_y):
corner_count += 1
4. Inefficient Point Checking Order
Checking all points for every potential rectangle can be inefficient. The current implementation continues checking even after finding an invalid point:
# Current approach checks all points even after finding invalidity for x, y in points: # ... validation logic
While the code does return early on finding an invalid point, the order of checks could be optimized.
Solution: Check the most likely invalid points first (those closest to the rectangle center) or use spatial data structures for large datasets:
# Sort points by distance to rectangle center for earlier rejection
center_x, center_y = (min_x + max_x) / 2, (min_y + max_y) / 2
sorted_points = sorted(points, key=lambda p:
abs(p[0] - center_x) + abs(p[1] - center_y))
5. Not Validating All Four Corners Exist
A subtle bug occurs when assuming the four corners exist just because we found a valid rectangle. The code correctly checks for exactly 4 corners, but developers might forget this check:
# WRONG: Assuming corners exist without verification if no_interior_points: return True # Missing corner count validation
Solution: Always verify both conditions:
# CORRECT: Check both no interior points AND exactly 4 corners return corner_count == 4 # Implicitly handles no interior points
Which algorithm should you use to find a node that is close to the root of the tree?
Recommended Readings
Segment Tree Faster Range Queries For this article we want to introduce the idea of a Segment Tree Segment Trees allow us to quickly perform range queries as well as range updates Suppose we have an array and we want to know the sum of a particular range of numbers as well
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Want a Structured Path to Master System Design Too? Don’t Miss This!