我们有 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个条件。
- (x_max - x_min)*(y_max - y_min) == face。
- 4个顶点只出现过一次。
- 其余顶点必然出现过偶数次。(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;
}
};
|