Leetcode:391.完美矩形

本文介绍了一种判断多个矩形是否能精确覆盖一个矩形区域的方法。通过计算总面积、检查顶点出现次数和验证四个角点的独特性,确保矩形完美拼接。使用哈希表记录顶点出现频率,确保除了四个角点外,其他顶点出现偶数次。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们有 N 个与坐标轴对齐的矩形, 其中 N > 0, 判断它们是否能精确地覆盖一个矩形区域。

每个矩形用左下角的点和右上角的点的坐标来表示。例如, 一个单位正方形可以表示为 [1,1,2,2]。 ( 左下角的点的坐标为 (1, 1) 以及右上角的点的坐标为 (2, 2) )。

示例 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],
  [3,2,4,4]
]

返回 false。图形顶端留有间隔,无法覆盖成一个矩形。

 

示例 4:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [1,3,2,4],
  [2,2,4,4]
]

返回 false。因为中间有相交区域,虽然形成了矩形,但不是精确覆盖。

解题思路:

逻辑题,数学题,哈希。如果明白完美矩形的数学描述以及非常规类型的哈希实现,那么这题就easy了。

完美矩形的数学描述:假设最终的区域里,s所有顶点的x_min,x_max,y_min,y_max被唯一确定,所有小的矩形的面积总和face。满足完美矩形需要3个条件。

  1. (x_max - x_min)*(y_max - y_min) == face。
  2. 4个顶点只出现过一次。
  3. 其余顶点必然出现过偶数次。(1次和3次都会出现空缺,代表不完美)

另外,判断某个顶点是否出现,需要用非常规类型的哈希实现。这个非常规类型是两个int。通过字符串流,可以将int转成字符串,然后将多个int转成的字符串相连,中间加入空格,组成的一个大字符串,就是我们最终要查询的对象。

stringstream ss;

ss<<int;

ss>>string; 

这样一来,别说两个int,多个int也是可以的。另外字符串流还可以转换其他类型,不仅仅是int,因此方法比较通用。我也看见过官方给出的运算速度最快的代码,方法基本类似,就是把两个int链接成了long long,效率更高,但是不能解决一般的非常规数据类型的hash, 因此各有各的好处。

int  a=123454,b=4345==>string res="123454 4345".

C++代码

class Solution {
public:
    
    bool isRectangleCover(vector<vector<int>>& rectangles) {
        int size = rectangles.size();
        int x_max = INT_MIN, x_min = INT_MAX, y_max = INT_MIN, y_min = INT_MAX;
        int face=0;
        stringstream ss;
        string x_str, y_str;
        unordered_map<string, int> mp;
        for (int i = 1; i <= size; i++) {
            int dx, dy;
            dx = abs(rectangles[i - 1][2] - rectangles[i - 1][0]);
            dy = abs(rectangles[i - 1][3] - rectangles[i - 1][1]);
            face += dx*dy;
            x_max = max(x_max, rectangles[i - 1][2]);
            x_max = max(x_max, rectangles[i - 1][0]);
            x_min = min(x_min, rectangles[i - 1][2]);
            x_min = min(x_min, rectangles[i - 1][0]);
            y_max = max(y_max, rectangles[i - 1][3]);
            y_max = max(y_max, rectangles[i - 1][1]);
            y_min = min(y_min, rectangles[i - 1][3]);
            y_min = min(y_min, rectangles[i - 1][1]);
            ss.clear();
            ss << rectangles[i - 1][0] << " " << rectangles[i - 1][1];
            ss >> x_str >> y_str;
            mp[x_str + " " + y_str]++;
            ss.clear();
            ss << rectangles[i - 1][2] << " " << rectangles[i - 1][3];
            ss >> x_str >> y_str;
            mp[x_str + " " + y_str]++;
            ss.clear();
            ss << rectangles[i - 1][0] << " " << rectangles[i - 1][3];
            ss >> x_str >> y_str;
            mp[x_str + " " + y_str]++;
            ss.clear();
            ss << rectangles[i - 1][2] << " " << rectangles[i - 1][1];
            ss >> x_str >> y_str;
            mp[x_str + " " + y_str]++;
        }
        if ((y_max - y_min)*(x_max - x_min) != face) return false;
        //4个顶点对应的字符串
        
        string UL, UR, DL, DR;
        ss.clear();
        ss << x_min << " " << y_max;
        ss >> x_str >> y_str;
        UL = x_str +" "+ y_str;
        ss.clear();
        ss << x_max << " " << y_max;
        ss >> x_str >> y_str;
        UR = x_str + " " + y_str;
        ss.clear();
        ss << x_min << " " << y_min;
        ss >> x_str >> y_str;
        DL = x_str + " " + y_str;
        ss.clear();
        ss << x_max << " " << y_min;
        ss >> x_str >> y_str;
        DR = x_str + " " + y_str;

        if (mp[UL] != 1 || mp[UR] != 1 || mp[DL] != 1 || mp[DR] != 1) {
            return false;
        }
        unordered_map<string, int>::iterator it;
        for (it = mp.begin(); it != mp.end(); it++) {
            if (it->second % 2 == 1) {
                if (!(it->first == UL || it->first == UR || it->first == DL || it->first == DR)) {
                    return false;
                }
            }
        }
        return true;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值