391. 完美矩形

391. 完美矩形

给你一个数组 rectangles ,其中 rectangles[i] = [xi, yi, ai, bi] 表示一个坐标轴平行的矩形。这个矩形的左下顶点是 (xi, yi) ,右上顶点是 (ai, bi) 。

如果所有矩形一起精确覆盖了某个矩形区域,则返回 true ;否则,返回 false 。

示例 1:

image.png
输入:rectangles = [[1,1,3,3],[3,1,4,2],[3,2,4,4],[1,3,2,4],[2,3,3,4]]
输出:true
解释:5 个矩形一起可以精确地覆盖一个矩形区域。
示例 2:
image.png

输入:rectangles = [[1,1,2,3],[1,3,2,4],[3,1,4,2],[3,2,4,4]]
输出:false
解释:两个矩形之间有间隔,无法覆盖成一个矩形。
示例 3:

image.png

输入:rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[3,2,4,4]]
输出:false
解释:图形顶端留有空缺,无法覆盖成一个矩形。
示例 4:

image.png

输入:rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[2,2,4,4]]
输出:false
解释:因为中间有相交区域,虽然形成了矩形,但不是精确覆盖。

提示:

  • 1 <= rectangles.length <= 2 * 1 0 4 10^4 104
  • rectangles[i].length == 4
  • − 1 0 5 -10^5 105 <= xi, yi, ai, bi <= 1 0 5 10^5 105

解题思路

首先所有矩形需要组合成一个大的正常矩形,因此矩形之间不能存在空缺。并且因为矩形之间如果存在相交区域,虽然形成了矩形,但就不是精确覆盖了。

  1. 因此我们需要保证所有小矩形加起来的面积等于大矩形
  2. 其次如果我们要保证没有重叠的部分,就需要统计每个顶点出现的次数,除了大矩形的四个顶点以外,每个顶点只能出现2次或者4次。如下图所示,如果出现了重叠的部分,那么就会出现出现次数为1的顶点
    image.png

因此,在算法中,我们需要统计每个小矩形顶点的出现次数和其面积,只有当其满足上述两个条件,才能实现精准覆盖

代码

typedef pair<int, int> point;

class Solution {
public:
    bool isRectangleCover(vector<vector<int>> &rectangles) {

        map<point, int> m;
        long long area(0);
        int min_x1(rectangles[0][0]),min_y1(rectangles[0][1]),max_y2(rectangles[0][3]),max_x2(rectangles[0][2]);
        for (auto p:rectangles) {
            int x1 = p[0], y1 = p[1], x2 = p[2], y2 = p[3];

            min_x1=min(x1,min_x1);
            min_y1=min(y1,min_y1);
            max_x2=max(x2,max_x2);
            max_y2=max(y2,max_y2);

            m[{x1,y1}]+=1;
            m[{x1,y2}]+=1;
            m[{x2,y1}]+=1;
            m[{x2,y2}]+=1;

            area+=abs(x1-x2)*abs(y1-y2);
        }

        point p1{min_x1,min_y1},p2{min_x1,max_y2},p3{max_x2,min_y1},p4{max_x2,max_y2};
        if ((long long )abs(min_x1-max_x2)*(long long )abs(max_y2-min_y1)!=area||!m.count(p1)||!m.count(p2)||!m.count(p3)||!m.count(p4))
            return false;

        m.erase(p1);
        m.erase(p2);
        m.erase(p3);
        m.erase(p4);

        for(auto item:m){
            if (item.second!=2&&item.second!=4)
                return false;
        }
        return true;

    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值