Skip to content

Latest commit

 

History

History
193 lines (119 loc) · 5.69 KB

0963._Minimum_Area_Rectangle_II.md

File metadata and controls

193 lines (119 loc) · 5.69 KB

963. Minimum Area Rectangle II

难度: Medium

刷题内容

原题连接

内容描述

Given a set of points in the xy-plane, determine the minimum area of any rectangle formed from these points, with sides not necessarily parallel to the x and y axes.

If there isn't any rectangle, return 0.

 

Example 1:



Input: [[1,2],[2,1],[1,0],[0,1]]
Output: 2.00000
Explanation: The minimum area rectangle occurs at [1,2],[2,1],[1,0],[0,1], with an area of 2.
Example 2:



Input: [[0,1],[2,1],[1,1],[1,0],[2,0]]
Output: 1.00000
Explanation: The minimum area rectangle occurs at [1,0],[1,1],[2,1],[2,0], with an area of 1.
Example 3:



Input: [[0,3],[1,2],[3,1],[1,3],[2,1]]
Output: 0
Explanation: There is no possible rectangle to form from these points.
Example 4:



Input: [[3,1],[1,1],[0,1],[2,1],[3,3],[3,2],[0,2],[2,3]]
Output: 2.00000
Explanation: The minimum area rectangle occurs at [2,1],[2,3],[3,3],[3,1], with an area of 2.
 

Note:

1 <= points.length <= 50
0 <= points[i][0] <= 40000
0 <= points[i][1] <= 40000
All points are distinct.
Answers within 10^-5 of the actual value will be accepted as correct.

解题方案

思路 1 - 时间复杂度: O(N^3)- 空间复杂度: O(N)******

现将points全部存到lookup里面

三轮循环,每轮循环分别取一个点,p1,p2,p3,然后看看直线p1-p2和直线p1-p3是否是互相垂直的,因为我们打算让p2和p3作为对角线 (其实一共有三种组合方式,p2-p3,p1-p2,p1-p3都可以作为对角线)

  1. 如果互相垂直,那么算出最后一个点的坐标看看是否在lookup里面
  • 如果在,算出面积,更新
  • 如果不在,continue
  1. 如果不相互垂直,continue
class Solution(object):
    def minAreaFreeRect(self, points):
        """
        :type points: List[List[int]]
        :rtype: float
        """
        lookup = {}
        for p in points:
            x, y = p
            lookup[(x,y)] = 1
        res = sys.maxsize
        for i in range(len(points)):
            x1, y1 = points[i]
            for j in range(i+1, len(points)):
                x2, y2 = points[j]
                for k in range(j+1, len(points)):
                    x3, y3 = points[k]
                    
                    if self.isValidRectangle(x1, x2, x3, y1, y2, y3):
                        x4, y4 = self.getP4(x1, x2, x3, y1, y2, y3)
                        if (x4, y4) in lookup:
                            res = min(res, self.getArea(x1, x2, x3, y1, y2, y3))
                        
                    if self.isValidRectangle(x2, x1, x3, y2, y1, y3):
                        x4, y4 = self.getP4(x2, x1, x3, y2, y1, y3)
                        if (x4, y4) in lookup:
                            res = min(res, self.getArea(x2, x1, x3, y2, y1, y3))
                        
                    if self.isValidRectangle(x3, x2, x1, y3, y2, y1):
                        x4, y4 = self.getP4(x3, x2, x1, y3, y2, y1)
                        if (x4, y4) in lookup:
                            res = min(res, self.getArea(x3, x2, x1, y3, y2, y1))
        return res if res != sys.maxsize else 0
                        
    # line p1-p2 and line p1-p3 are Perpendicular to each other                 
    def isValidRectangle(self, x1, x2, x3, y1, y2, y3): 
        return (x2-x1) * (x3-x1) + (y2-y1) * (y3-y1) == 0
    
    def getP4(self, x1, x2, x3, y1, y2, y3):
        return [x3 - x1 + x2, y3 - y1 + y2]
    
    def getArea(self, x1, x2, x3, y1, y2, y3):
        return math.sqrt((x2-x1)**2 + (y2-y1)**2) * math.sqrt((x3-x1)**2 + (y3-y1)**2)

思路 2 - 时间复杂度: O(N^2)- 空间复杂度: O(N)******

其实这个时间可以得到优化,我们可以做两次循环,每次取得一个点,p1,p2,我们认为p1和p2组成的连线就是对角线

我们将一条对角线的距离和其中点的坐标作为key,p1和p2在points中的index作为value存起来,value默认是一个list

这样如果有一个key的value的长度大于1,那么就说明有两条不同的直线,他们的长度相等并且连线的中点也一样,那么这两条对角线所对应的4个点肯定可以组成一个矩形

那么我们拿出一条对角线,取得上面的两个点p1,p2,然后从另外一条对角线上取得一个点p3,直线p1-p2是对角线,p3到p1和p2的距离即为矩形的长和宽, 求出面积之后更新res即可

这样我们的时间就得到了优化,O(N^2)

class Solution(object):
    def minAreaFreeRect(self, points):
        """
        :type points: List[List[int]]
        :rtype: float
        """
        lookup = collections.defaultdict(list)
        for i in range(len(points)):
            x1, y1 = points[i]
            for j in range(i+1, len(points)):
                x2, y2 = points[j]
                dist = (x1-x2) ** 2 + (y1-y2) ** 2
                cx, cy = (x1 + x2) / 2, (y1 + y2) / 2
                key = (dist, cx, cy)
                lookup[key].append((i, j))
                
        res = sys.maxsize
        for k, v in lookup.items():
            if len(v) > 1:
                for i in range(len(v)):
                    for j in range(i+1, len(v)):
                        x1, y1 = points[v[i][0]]
                        x2, y2 = points[v[i][1]]
                        x3, y3 = points[v[j][0]] # 直线p1-p2是对角线,p3到p1和p2的距离即为矩形的长和宽
                        length = math.sqrt((x3-x1)**2 + (y3-y1)**2)
                        width = math.sqrt((x3-x2)**2 + (y3-y2)**2)
                        area = length * width
                        res = min(res, area)
        return res if res != sys.maxsize else 0