939. Minimum Area Rectangle(python+cpp)

题目:

Given a set of points in the xy-plane, determine the minimum area of a rectangle formed from these points, with sides parallel to the x and y axes.
If there isn’t any rectangle, return 0.
Example 1:

Input: [[1,1],[1,3],[3,1],[3,3],[2,2]] 
Output: 4 

Example 2:

Input: [[1,1],[1,3],[3,1],[3,3],[4,1],[4,3]] 
Output: 2  

Note:
1 <= points.length <= 500
0 <= points[i][0] <= 40000
0 <= points[i][1] <= 40000
All points are distinct.

解释:
四个点一定要作为长方形的四个顶点,两点(对角线)确定一个长方形
1.遍历所有的点对,找到所有的点对,最后找到面积最小的,将x相同的点,其y放在一个列表中(或者反过来),也就是建立一个key为x,value为列表的字典。
天哪,为什么python超时?
2.还是这样的思想,还是对角线确定矩阵方法,把遍历过的点放到一个set()中。
python代码,hashmap思想,超时:

from collections import defaultdict
class Solution:
    def minAreaRect(self, points):
        """
        :type points: List[List[int]]
        :rtype: int
        """
        _dict=defaultdict(list)
        for point in points:
            _dict[point[0]].append(point[1])
        min_area=float('inf')
        #遍历所有的点对:
        n=len(points)
        points.sort()
        for i in range(n):
            for j in range(i+1,n):
                x1,y1=points[i]
                x2,y2=points[j]
                if x1==x2 or y1==y2:
                    continue
                elif (y2 in _dict[x1]) and (y1 in _dict[x2]):
                    min_area=min(min_area,abs(x1-x2)*abs(y1-y2))
        return 0 if min_area==float('inf') else min_area

python代码,set()思想,1500ms,速度极慢:

class Solution:
    def minAreaRect(self, points):
        """
        :type points: List[List[int]]
        :rtype: int
        """
        seen=set()
        min_area=float('inf')
        for x1,y1 in points:
            for x2,y2 in seen:
                if (x1,y2) in seen and (x2,y1) in seen:
                    min_area=min(min_area,abs(x1-x2)*abs(y1-y2))
            seen.add((x1,y1))
        return 0 if min_area==float('inf') else min_area
        

测试用例有诸如 all points have x = 0 or y = 0的极端情况,下面的代码避免这种情况带来的耗时问题。
一个特别牛逼的字典思想

from collections import defaultdict
class Solution:
    def minAreaRect(self, points):
        """
        :type points: List[List[int]]
        :rtype: int
        """
        setx=set()
        sety=set()
        for point in points:
            setx.add(point[0])
            sety.add(point[1])
        _dict=defaultdict(list)
        if len(setx)>len(sety):
            for _x,_y in points:
                _dict[_x].append(_y)
        else:
            for _x,_y in points:
                _dict[_y].append(_x)
        min_area=float('inf')
        lastx={}
        for x in sorted(_dict):
            _dict[x].sort()
            for i in range(len(_dict[x])):
                #每个点只和自己下面的点比较,求面积的时候不需要求abs了
                for j in range(i):
                    y1,y2=_dict[x][j],_dict[x][i]
                    if (y1,y2) in lastx:
                        min_area=min(min_area,(x-lastx[(y1,y2)])*(y2-y1))
                    lastx[(y1,y2)]=x
        return 0 if min_area==float('inf') else min_area

c++代码:

#include <set>
using namespace std;
class Solution {
public:
    int minAreaRect(vector<vector<int>>& points) {
        set<int> setx;
        set<int> sety;
        for (auto point:points)
        {
            setx.insert(point[0]);
            sety.insert(point[1]);
        }
        map<int ,vector<int>> _map;
        if (setx.size()>sety.size())
        {
            for(auto point :points)
                _map[point[0]].push_back(point[1]);
        }
        else
        {
            for(auto point :points)
                _map[point[1]].push_back(point[0]);
        }
        int min_area=INT_MAX;
        map<vector<int>,int>lastx;
        for (auto item:_map)
        {
            sort(item.second.begin(),item.second.end());
            for(int i =0;i<item.second.size();i++)
            {
                for(int j=0;j<i;j++)
                {
                    int y1=item.second[j];
                    int y2=item.second[i];
                    if (lastx.count({y1,y2}))
                    {
                        min_area=min(min_area,(item.first-lastx[{y1,y2}])*(y2-y1));
                    }
                    lastx[{y1,y2}]=item.first;
                }
            }
        }
        return min_area==INT_MAX?0:min_area;    
    }
};

总结:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值