目录

0963:最小面积矩形 II(1990 分)

力扣第 116 场周赛第 3 题

题目

给你一个 X-Y 平面上的点数组 points,其中 points[i] = [xi, yi]

返回由这些点形成的任意矩形的最小面积,矩形的边 不一定 平行于 X 轴和 Y 轴。如果不存在这样的矩形,则返回 0

答案只需在10-5 的误差范围内即可被视作正确答案。

示例 1:

输入: points = [[1,2],[2,1],[1,0],[0,1]]
输出: 2.00000
解释: 最小面积矩形由 [1,2]、[2,1]、[1,0]、[0,1] 组成,其面积为 2。

示例 2:

输入: points = [[0,1],[2,1],[1,1],[1,0],[2,0]]
输出: 1.00000
解释: 最小面积矩形由 [1,0]、[1,1]、[2,1]、[2,0] 组成,其面积为 1。

示例 3:

输入: points = [[0,3],[1,2],[3,1],[1,3],[2,1]]
输出: 0
解释: 无法由这些点组成任何矩形。

提示:

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

分析

#1

  • 最简单的就是遍历三个点,判断形成的两条边是否垂直,并判断对应的第四个点是否存在
  • 判断垂直可以用内积,计算面积可以用外积
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def dot(u,v):    # u·v,点乘(内积)
    return u[0]*v[0]+u[1]*v[1]

def cross(u,v):  # u X v,叉乘(外积),逆正顺负
    return u[0]*v[1]-u[1]*v[0]

class Solution:
    def minAreaFreeRect(self, points: List[List[int]]) -> float:
        vis = {(x,y) for x,y in points}
        res = inf
        for p1, p2, p3 in permutations(points, 3):
            p4 = p2[0] + p3[0] - p1[0], p2[1] + p3[1] - p1[1]
            if p4 in vis:
                v1 = (p2[0] - p1[0], p2[1] - p1[1])
                v2 = (p3[0] - p1[0], p3[1] - p1[1])
                if dot(v1,v2)==0:
                    area = abs(cross(v1,v2))
                    if area < res:
                        res = area
        return res if res < inf else 0

687 ms

#2

  • 还可以按对角线分组,矩形的两条对角线满足:
    • 中点相同、长度相等
  • 同一组内,夹角更小的两条对角线组成的矩形面积更小
  • 因此组内极角排序,计算相邻对角线的外积即可

解答

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
def cross(u,v):  # u X v,叉乘(外积),逆正顺负
    return u[0]*v[1]-u[1]*v[0]

class Solution:
    def minAreaFreeRect(self, points: List[List[int]]) -> float:
        n = len(points)
        d = defaultdict(list)
        for i in range(n):
            for j in range(i+1,n):
                u,v = sorted([points[i],points[j]])
                mid = (u[0]+v[0],u[1]+v[1])
                p = [v[0]-u[0],v[1]-u[1]]
                r = p[0]**2+p[1]**2
                d[(mid,r)].append(p)
        res = inf
        for A in d.values():
            A.sort(key=lambda u: atan2(u[1],u[0]))
            if len(A)>1:
                for u,v in zip(A,A[1:]+A[:1]):
                    res = min(res,abs(cross(u,v)))
        return res/2 if res<inf else 0

54 ms