leetcode 939. Minimum Area Rectangle

题目

在这里插入图片描述
在这里插入图片描述

解法1:暴力n*n解法

循环所有点的pair,尝试用这两个点组成矩形

class Solution:
    def minAreaRect(self, points: List[List[int]]) -> int:
        points_dict = set()
        for x,y in points:
            points_dict.add((x,y))
        
        min_area = float('inf')
        for x1,y1 in points:
            for x2,y2 in points:
                if x1 > x2 and y1 > y2:
                    if (x1,y2) in points_dict and (x2,y1) in points_dict:
                        area = (y1-y2) * (x1-x2)
                        min_area = min(area,min_area)
        return min_area if min_area != float('inf') else 0

这边比较有意思的事,如果把set换成dict会超时,说明这边这种dict搜索tuple的方式实际肯定不是O(1)

解法2:优化的暴力解法

对于每个点的pair,我们只考虑一个是top right和bottom left的情况,减少复杂度,为啥呢
举个例子:在example 1中,一开始先考虑了(1,1)和(3,3)作为对角点的情况,但是后面还是会考虑(1,3)和(3,1)作为对角点的情况,而这两种情况是一样的,所以就有重复计算
二现在的做法是,想办法只考虑(1,1)和(3,3)作为对角点的情况

class Solution:
    def minAreaRect(self, points: List[List[int]]) -> int:
        points_dict = set()
        for p in points:
            points_dict.add(tuple(p))
        
        min_area = float('inf')
        for x1,y1 in points:
            for x2,y2 in points:
                # why we only deal with x1 > x2 and y1 > y2 ???
                # because to avoid repeated computation, for a pair of point, we only deal with them when:
                # p1 is top right corner and p2 is bottom left point
                if x1 > x2 and y1 > y2:
                    if (x1,y2) in points_dict and (x2,y1) in points_dict:
                        area = (y1-y2) * (x1-x2)
                        min_area = min(area,min_area)
        return min_area if min_area != float('inf') else 0

解法3:

为了减少复杂度,将x或者y进行归类,用一种巧妙的方法去去除无需计算的矩形,这边最巧妙的点在于,利用排序只计算相邻两个x之间或者y之间的矩形,而无序计算其他的,因为其他的会面积更大

class Solution:
    def minAreaRect(self, points: List[List[int]]) -> int:
        n = len(points)
        # number of different x and different y
        nx = len(set(x for x,y in points))
        ny = len(set(y for x,y in points))
        # if nx == n, meaning every point has different value, no way to form a rectangle that's parallel to y axis
        if nx == n or ny == n:
            return 0
        
        p = collections.defaultdict(list)
        # we use the large number to the key because time is in (nx * ny * ny) or (nx * nx * ny)
        # so in this way the computation can be minimized
        if nx > ny:
            for x,y in points:
                p[x].append(y)
        else:
            for x,y in points:
                p[y].append(x)
        
        # thhis dict saves {(y1,y2):x}, which means the previous appeared x
        # why saved like this??? because for current x, and same y1,y2, the min area is guranteed to formed between the current x and the previous x
        # all x earlier than previous_x will have larger area
        previous_x2y = {}
        min_area = float('inf')
        # x need to be in order
        for x in sorted(p):
            p[x].sort()
            for i in range(len(p[x])):
                for j in range(i+1,len(p[x])):
                    y1,y2 = p[x][i],p[x][j]
                    if (y1,y2) in previous_x2y:
                        min_area = min(min_area,(x-previous_x2y[(y1,y2)])*(y2-y1))
                    previous_x2y[(y1,y2)] = x
        return min_area if min_area != float('inf') else 0

时间复杂度:O(nx * nx * ny) < O(N ^ 1.5)
具体时间复杂度分析如下:
在这里插入图片描述
参考:https://leetcode.com/problems/minimum-area-rectangle/discuss/192021/Python-O(N1.5)-80ms

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值