加载中...
939-最小面积矩形(Minimum Area Rectangle)
发表于:2021-12-03 | 分类: 中等
字数统计: 969 | 阅读时长: 5分钟 | 阅读量:

原文链接: 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. 1 <= points.length <= 500
  2. 0 <= points[i][0] <= 40000
  3. 0 <= points[i][1] <= 40000
  4. 所有的点都是不同的。

通过代码

官方题解

方法一:按列排序

我们将这些点按照 x 轴(即列)排序,那么对于同一列的两个点 (x, y1)(x, y2),我们找出它作为右边界的最小的矩形。这可以通过记录下我们之前遇到的所有 (y1, y2) 点对来做到。

[sol1]
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; } }
[sol1]
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) 是否也出现在集合中。

[sol2]
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; } }
[sol2]
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%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
937-重新排列日志文件(Reorder Data in Log Files)
下一篇:
938-二叉搜索树的范围和(Range Sum of BST)
本文目录
本文目录