原文链接: https://leetcode-cn.com/problems/minimum-area-rectangle
英文原文
You are given an array of points in the X-Y plane points
where points[i] = [xi, yi]
.
Return the minimum area of a rectangle formed from these points, with sides parallel to the X and Y axes. If there is not any such rectangle, return 0
.
Example 1:
Input: points = [[1,1],[1,3],[3,1],[3,3],[2,2]] Output: 4
Example 2:
Input: points = [[1,1],[1,3],[3,1],[3,3],[4,1],[4,3]] Output: 2
Constraints:
1 <= points.length <= 500
points[i].length == 2
0 <= xi, yi <= 4 * 104
- All the given points are unique.
中文题目
给定在 xy 平面上的一组点,确定由这些点组成的矩形的最小面积,其中矩形的边平行于 x 轴和 y 轴。
如果没有任何矩形,就返回 0。
示例 1:
输入:[[1,1],[1,3],[3,1],[3,3],[2,2]] 输出:4
示例 2:
输入:[[1,1],[1,3],[3,1],[3,3],[4,1],[4,3]] 输出:2
提示:
1 <= points.length <= 500
0 <= points[i][0] <= 40000
0 <= points[i][1] <= 40000
- 所有的点都是不同的。
通过代码
官方题解
方法一:按列排序
我们将这些点按照 x
轴(即列)排序,那么对于同一列的两个点 (x, y1)
和 (x, y2)
,我们找出它作为右边界的最小的矩形。这可以通过记录下我们之前遇到的所有 (y1, y2)
点对来做到。
class Solution {
public int minAreaRect(int[][] points) {
Map<Integer, List<Integer>> rows = new TreeMap();
for (int[] point: points) {
int x = point[0], y = point[1];
rows.computeIfAbsent(x, z-> new ArrayList()).add(y);
}
int ans = Integer.MAX_VALUE;
Map<Integer, Integer> lastx = new HashMap();
for (int x: rows.keySet()) {
List<Integer> row = rows.get(x);
Collections.sort(row);
for (int i = 0; i < row.size(); ++i)
for (int j = i+1; j < row.size(); ++j) {
int y1 = row.get(i), y2 = row.get(j);
int code = 40001 * y1 + y2;
if (lastx.containsKey(code))
ans = Math.min(ans, (x - lastx.get(code)) * (y2-y1));
lastx.put(code, x);
}
}
return ans < Integer.MAX_VALUE ? ans : 0;
}
}
class Solution(object):
def minAreaRect(self, points):
columns = collections.defaultdict(list)
for x, y in points:
columns[x].append(y)
lastx = {}
ans = float('inf')
for x in sorted(columns):
column = columns[x]
column.sort()
for j, y2 in enumerate(column):
for i in xrange(j):
y1 = column[i]
if (y1, y2) in lastx:
ans = min(ans, (x - lastx[y1,y2]) * (y2 - y1))
lastx[y1, y2] = x
return ans if ans < float('inf') else 0
复杂度分析
时间复杂度:$O(N^2)$,其中 $N$ 是数组
points
的长度。空间复杂度:$O(N)$。
方法二:枚举对角线
我们将所有点放入集合中,并枚举矩形对角线上的两个点,并判断另外两个点是否出现在集合中。例如我们在枚举到 (1, 1)
和 (5, 5)
时,我们需要判断 (1, 5)
和 (5, 1)
是否也出现在集合中。
class Solution {
public int minAreaRect(int[][] points) {
Set<Integer> pointSet = new HashSet();
for (int[] point: points)
pointSet.add(40001 * point[0] + point[1]);
int ans = Integer.MAX_VALUE;
for (int i = 0; i < points.length; ++i)
for (int j = i+1; j < points.length; ++j) {
if (points[i][0] != points[j][0] && points[i][1] != points[j][1]) {
if (pointSet.contains(40001 * points[i][0] + points[j][1]) &&
pointSet.contains(40001 * points[j][0] + points[i][1])) {
ans = Math.min(ans, Math.abs(points[j][0] - points[i][0]) *
Math.abs(points[j][1] - points[i][1]));
}
}
}
return ans < Integer.MAX_VALUE ? ans : 0;
}
}
class Solution(object):
def minAreaRect(self, points):
S = set(map(tuple, points))
ans = float('inf')
for j, p2 in enumerate(points):
for i in xrange(j):
p1 = points[i]
if (p1[0] != p2[0] and p1[1] != p2[1] and
(p1[0], p2[1]) in S and (p2[0], p1[1]) in S):
ans = min(ans, abs(p2[0] - p1[0]) * abs(p2[1] - p1[1]))
return ans if ans < float('inf') else 0
时间复杂度:$O(N^2)$,其中 $N$ 是数组
points
的长度。空间复杂度:$O(N)$。
统计信息
通过次数 | 提交次数 | AC比率 |
---|---|---|
5879 | 12852 | 45.7% |
提交历史
提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
---|