Medium

题目描述

给你一个数组 points,其中 points[i] = [xi, yi] 表示无限平面上一个点的坐标。

你的任务是找到一个矩形的最大面积,该矩形满足:

  • 可以使用这些点中的四个作为其角点来形成。
  • 内部或边界上不包含任何其他点。
  • 其边平行于坐标轴。

返回你能获得的最大面积,如果无法形成这样的矩形,则返回 -1

示例 1:

输入:points = [[1,1],[1,3],[3,1],[3,3]]
输出:4
解释:我们可以用这4个点作为角点构成一个矩形,没有其他点位于内部或边界上。因此,最大可能面积为4。

示例 2:

输入:points = [[1,1],[1,3],[3,1],[3,3],[2,2]]
输出:-1
解释:只能构成一个矩形,角点为[1,1], [1,3], [3,1], [3,3],但[2,2]总是在其内部。因此返回-1。

示例 3:

输入:points = [[1,1],[1,3],[3,1],[3,3],[1,2],[3,2]]
输出:2
解释:最大面积矩形由点[1,3], [1,2], [3,2], [3,3]形成,面积为2。另外,点[1,1], [1,2], [3,1], [3,2]也形成一个相同面积的有效矩形。

约束条件:

  • 1 <= points.length <= 10
  • points[i].length == 2
  • 0 <= xi, yi <= 100
  • 所有给定的点都是唯一的。

提示:

  • 如果 (x1, y1)(x2, y2) 是矩形的两个对角,那么另外两个角点是 (x1, y2)(x2, y1)
  • 固定两个点,使用集合数据结构找到另外两个点。
  • 确定矩形后,遍历点数组确保没有点位于矩形的边界或内部。

解题思路

这道题要求我们找到最大面积的轴对齐矩形,且矩形内部和边界上不能有其他点。

核心思路:

  1. 枚举对角点对:由于边平行于坐标轴,我们可以枚举所有可能的对角点对 (x1,y1)(x2,y2),其中 x1 != x2y1 != y2

  2. 验证矩形存在性:对于每对对角点,另外两个角点必须是 (x1,y2)(x2,y1)。我们需要验证这两个点是否在给定点集中。

  3. 检查约束条件:对于每个有效的矩形,我们需要检查是否有其他点位于矩形内部或边界上。如果有,则该矩形不符合要求。

  4. 计算最大面积:在所有符合条件的矩形中,选择面积最大的。

算法步骤:

  • 将所有点存储在集合中便于快速查找
  • 枚举所有点对作为潜在的对角点
  • 对每对对角点,检查是否能形成完整矩形
  • 验证矩形内部和边界是否包含其他点
  • 更新最大面积

时间复杂度为 O(n³),其中 n 是点的数量。由于 n ≤ 10,这个复杂度是可接受的。

代码实现

class Solution {
public:
    int maxRectangleArea(vector<vector<int>>& points) {
        int n = points.size();
        set<pair<int, int>> pointSet;
        
        for (auto& p : points) {
            pointSet.insert({p[0], p[1]});
        }
        
        int maxArea = -1;
        
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int x1 = points[i][0], y1 = points[i][1];
                int x2 = points[j][0], y2 = points[j][1];
                
                if (x1 == x2 || y1 == y2) continue;
                
                if (pointSet.count({x1, y2}) && pointSet.count({x2, y1})) {
                    bool valid = true;
                    
                    int minX = min(x1, x2), maxX = max(x1, x2);
                    int minY = min(y1, y2), maxY = max(y1, y2);
                    
                    for (auto& p : points) {
                        int x = p[0], y = p[1];
                        if ((x == x1 && y == y1) || (x == x1 && y == y2) ||
                            (x == x2 && y == y1) || (x == x2 && y == y2)) {
                            continue;
                        }
                        
                        if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
                            valid = false;
                            break;
                        }
                    }
                    
                    if (valid) {
                        int area = abs(x2 - x1) * abs(y2 - y1);
                        maxArea = max(maxArea, area);
                    }
                }
            }
        }
        
        return maxArea;
    }
};
class Solution:
    def maxRectangleArea(self, points: List[List[int]]) -> int:
        n = len(points)
        point_set = set((x, y) for x, y in points)
        
        max_area = -1
        
        for i in range(n):
            for j in range(i + 1, n):
                x1, y1 = points[i]
                x2, y2 = points[j]
                
                if x1 == x2 or y1 == y2:
                    continue
                
                if (x1, y2) in point_set and (x2, y1) in point_set:
                    valid = True
                    
                    min_x, max_x = min(x1, x2), max(x1, x2)
                    min_y, max_y = min(y1, y2), max(y1, y2)
                    
                    for x, y in points:
                        if (x, y) in [(x1, y1), (x1, y2), (x2, y1), (x2, y2)]:
                            continue
                        
                        if min_x <= x <= max_x and min_y <= y <= max_y:
                            valid = False
                            break
                    
                    if valid:
                        area = abs(x2 - x1) * abs(y2 - y1)
                        max_area = max(max_area, area)
        
        return max_area
public class Solution {
    public int MaxRectangleArea(int[][] points) {
        int n = points.Length;
        HashSet<(int, int)> pointSet = new HashSet<(int, int)>();
        
        foreach (var p in points) {
            pointSet.Add((p[0], p[1]));
        }
        
        int maxArea = -1;
        
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int x1 = points[i][0], y1 = points[i][1];
                int x2 = points[j][0], y2 = points[j][1];
                
                if (x1 == x2 || y1 == y2) continue;
                
                if (pointSet.Contains((x1, y2)) && pointSet.Contains((x2, y1))) {
                    bool valid = true;
                    
                    int minX = Math.Min(x1, x2), maxX = Math.Max(x1, x2);
                    int minY = Math.Min(y1, y2), maxY = Math.Max(y1, y2);
                    
                    foreach (var p in points) {
                        int x = p[0], y = p[1];
                        if ((x == x1 && y == y1) || (x == x1 && y == y2) ||
                            (x == x2 && y == y1) || (x == x2 && y == y2)) {
                            continue;
                        }
                        
                        if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
                            valid = false;
                            break;
                        }
                    }
                    
                    if (valid) {
                        int area = Math.Abs(x2 - x1) * Math.Abs(y2 - y1);
                        maxArea = Math.Max(maxArea, area);
                    }
                }
            }
        }
        
        return maxArea;
    }
}
/**
 * @param {number[][]} points
 * @return {number}
 */
var maxRectangleArea = function(points) {
    const n = points.length;
    if (n < 4) return -1;
    
    let maxArea = -1;
    
    // Try all combinations of 4 points
    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            for (let k = j + 1; k < n; k++) {
                for (let l = k + 1; l < n; l++) {
                    const rect = [points[i], points[j], points[k], points[l]];
                    
                    // Check if these 4 points form a valid rectangle
                    if (isValidRectangle(rect)) {
                        // Check if no other points are inside or on border
                        if (noPointsInside(rect, points)) {
                            const area = calculateArea(rect);
                            maxArea = Math.max(maxArea, area);
                        }
                    }
                }
            }
        }
    }
    
    return maxArea;
};

function isValidRectangle(points) {
    const xs = [...new Set(points.map(p => p[0]))].sort((a, b) => a - b);
    const ys = [...new Set(points.map(p => p[1]))].sort((a, b) => a - b);
    
    if (xs.length !== 2 || ys.length !== 2) return false;
    
    const corners = new Set(points.map(p => `${p[0]},${p[1]}`));
    
    return corners.has(`${xs[0]},${ys[0]}`) &&
           corners.has(`${xs[0]},${ys[1]}`) &&
           corners.has(`${xs[1]},${ys[0]}`) &&
           corners.has(`${xs[1]},${ys[1]}`);
}

function noPointsInside(rectPoints, allPoints) {
    const xs = [...new Set(rectPoints.map(p => p[0]))].sort((a, b) => a - b);
    const ys = [...new Set(rectPoints.map(p => p[1]))].sort((a, b) => a - b);
    
    const rectCorners = new Set(rectPoints.map(p => `${p[0]},${p[1]}`));
    
    for (const point of allPoints) {
        if (!rectCorners.has(`${point[0]},${point[1]}`)) {
            if (point[0] >= xs[0] && point[0] <= xs[1] && 
                point[1] >= ys[0] && point[1] <= ys[1]) {
                return false;
            }
        }
    }
    
    return true;
}

function calculateArea(points) {
    const xs = [...new Set(points.map(p => p[0]))].sort((a, b) => a - b);
    const ys = [...new Set(points.map(p => p[1]))].sort((a, b) => a - b);
    
    return (xs[1] - xs[0]) * (ys[1] - ys[0]);
}

复杂度分析

项目复杂度
时间复杂度O(n³)
空间复杂度O(n)

其中 n 是点的数量。时间复杂度为 O(n³) 是因为我们需要枚举所有点对(O(n²)),并对每个潜在矩形检查所有其他点(O(n))。空间复杂度为 O(n),用于存储点集合。

相关题目