leetcode 391. 完美矩形—(每日一难day14)

该博客探讨了一种算法问题,即如何判断给定的一组矩形是否能精确覆盖一个大矩形区域。通过分析每个矩形的顶点出现次数以及总面积,可以确定是否存在精确覆盖。关键在于检查四周顶点出现次数和剩余顶点的分布情况。算法涉及到了几何、数据结构和哈希映射的应用。
摘要由CSDN通过智能技术生成

391. 完美矩形

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

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

示例 1:

输入:rectangles = [[1,1,3,3],[3,1,4,2],[3,2,4,4],[1,3,2,4],[2,3,3,4]]
输出:true
解释:5 个矩形一起可以精确地覆盖一个矩形区域。
在这里插入图片描述

示例 2:

输入:rectangles = [[1,1,2,3],[1,3,2,4],[3,1,4,2],[3,2,4,4]]
输出:false
解释:两个矩形之间有间隔,无法覆盖成一个矩形。
在这里插入图片描述

示例 3:

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

提示:

1 <= rectangles.length <= 2 * 1e4
rectangles[i].length == 4
-1e5 <= xi, yi, ai, bi <= 1e5

解析

  1. 记录每个矩形的每个顶点出现的次数,如果两个矩形重叠,那么矩形中一定有顶点会重复出现1次或者3次。
  2. 对于大矩形最外侧四个顶点,一定只能出现一次
  3. 如果出现空白和重叠,大矩形面积一定不等于所有矩形面积之和(防止完全重合的情况 [[0,0,4,1],[0,0,4,1]]
  4. 因此,需要统计每个点出现的次数,使用map<pair<int,int>,int>可以记录,这里我们使用map<x1000+y,cnt>记录,这种情况不一定100%正确,可能会出现不同点,但是x1000+y值相同情况。
  5. 满足条件的组合方式图示:
    在这里插入图片描述
    在这里插入图片描述

code


 class Solution {
public:
    // 覆盖的最大区域可以根据右上角,左下角确定
    bool isRectangleCover(vector<vector<int>>& r) {
        int n=r.size();
        // 寻找四周的最大值最小值
        int min_left = r[0][0],min_down=r[0][1],max_right=r[0][2],max_up=r[0][3];
        // 记录点出现次数
        unordered_map<long long,int> ma;
        // 面积(判断是否重叠)
        long area=0;
        for(auto r1:r){
            min_left=min(min_left,r1[0]);
            min_down=min(min_down,r1[1]);
            max_right=max(max_right,r1[2]);
            max_up=max(max_up,r1[3]);
            area+=(long)(r1[2]-r1[0])*(r1[3]-r1[1]);
            // 记录每个点出现的次数
            ma[1000*r1[0]+r1[1]]++;
            ma[1000*r1[0]+r1[3]]++;
            ma[1000*r1[2]+r1[3]]++;
            ma[1000*r1[2]+r1[1]]++;
        }

        // 判断四个外侧顶点
        if(area!=(long)(max_right-min_left)*(max_up-min_down)||
                    ma.count(min_left*1000+min_down)!=1||
                    ma.count(min_left*1000+max_up)!=1||
                    ma.count(max_right*1000+min_down)!=1||
                    ma.count(max_right*1000+max_up)!=1){
                //cout<<1<<endl;
                return false;
        }
        // 去除四个最外侧顶点
        ma.erase(min_left*1000+min_down);
        ma.erase(min_left*1000+max_up);
        ma.erase(max_right*1000+min_down);
        ma.erase(max_right*1000+max_up);

        // 剩余顶点个数必须为2/4
        for(auto a : ma){
            if(a.second!=2&&a.second!=4)
                return false;
        }   

        return true;
        

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值