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