「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」
题目
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],[3,2,4,4]]
输出:false 解释:图形顶端留有空缺,无法覆盖成一个矩形。
示例 4:
输入:rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[2,2,4,4]]
输出:false 解释:因为中间有相交区域,虽然形成了矩形,但不是精确覆盖。
提示:
1 <= rectangles.length <= 2 * 104
rectangles[i].length == 4
-105 <= xi, yi, ai, bi <= 105
思路
开始我的想法是求出最大点的坐标和最小的坐标,以此求出整个大矩形的面积,然后把每个小矩形面积相加,如果相等则符合,这种想法可以通过很多测试用例,但是在测试用例[[0, 0, 1, 1],[0, 1, 3, 2],[1, 0, 2, 2]]时报错了,图形如下:
三个矩形分别用蓝色、紫色、橙色框框代替,中间重叠的部分是米色部分进行表示,很显然重合的地方与缺少的部分相抵消,证明用这种方法不行。
我们对着图片好好看一下,发现如果是完美矩形则这些小矩形的每个顶点都会相互抵消,只留下大矩形四个顶点,而非完美矩形则不止四个顶点,我们可以把这些小矩形的坐标存在一个数组或者集合中,当再次遇见这个坐标时进行移除,把所有小矩形的四个顶点都遍历结束后,应该只剩下大矩形的四个顶点。按照这种思路写代码。
代码
// 执行用时:136 ms, 在所有 JavaScript 提交中击败了72.22%的用户
// 内存消耗:49.4 MB, 在所有 JavaScript 提交中击败了61.11%的用户
var isRectangleCover = function (rectangles) {
let area = 0;
let minx = rectangles[0][0],
miny = rectangles[0][1],
maxx = rectangles[0][2],
maxy = rectangles[0][3];
let coordinateSets = new Set();
for (let i = 0; i < rectangles.length; i++) {
let coordinates = [];
coordinates[0] = rectangles[i][0].toString() + rectangles[i][1].toString();
coordinates[1] = rectangles[i][0].toString() + rectangles[i][3].toString();
coordinates[2] = rectangles[i][2].toString() + rectangles[i][1].toString();
coordinates[3] = rectangles[i][2].toString() + rectangles[i][3].toString();
for (let i = 0; i < 4; i++) {
if (coordinateSets.has(coordinates[i])) {
coordinateSets.delete(coordinates[i])
} else {
coordinateSets.add(coordinates[i])
}
}
let temparea = (rectangles[i][2] - rectangles[i][0]) * (rectangles[i][3] - rectangles[i][1]);
area += temparea;
minx = Math.min(minx, rectangles[i][0]);
miny = Math.min(miny, rectangles[i][1]);
maxx = Math.max(maxx, rectangles[i][2]);
maxy = Math.max(maxy, rectangles[i][3]);
}
let finarea = (maxx - minx) * (maxy - miny);
let res;
if (area === finarea && coordinateSets.size === 4) {
res = true;
} else {
res = false;
}
let fincoordinates = [];
fincoordinates[0] = minx.toString() + miny.toString();
fincoordinates[1] = minx.toString() + maxy.toString();
fincoordinates[2] = maxx.toString() + maxy.toString();
fincoordinates[3] = maxx.toString() + miny.toString();
for (let i = 0; i < 4; i++) {
if (!coordinateSets.has(fincoordinates[i])) {
res = false;
}
}
return res;
console.log(res);
console.log(coordinateSets);
console.log(fincoordinates);
// console.log(area);
console.log(minx);
console.log(miny);
console.log(maxx);
console.log(maxy);
};
// isRectangleCover([
// [1, 1, 3, 3],
// [3, 1, 4, 2],
// [3, 2, 4, 4],
// [1, 3, 2, 4],
// [2, 3, 3, 4]
// ])
// console.log("---------");
// isRectangleCover([
// [1, 1, 2, 3],
// [1, 3, 2, 4],
// [3, 1, 4, 2],
// [3, 2, 4, 4]
// ])
// console.log("---------");
// isRectangleCover([
// [
// [1, 1, 3, 3],
// [3, 1, 4, 2],
// [1, 3, 2, 4],
// [3, 2, 4, 4]
// ]
// ])
// console.log("---------");
// isRectangleCover([
// [1, 1, 3, 3],
// [3, 1, 4, 2],
// [1, 3, 2, 4],
// [2, 2, 4, 4]
// ])
// console.log("---------");
isRectangleCover([
[0, 0, 1, 1],
[0, 1, 3, 2],
[1, 0, 2, 2]
])
// // // false
// console.log("---------");
// isRectangleCover([
// [0, 0, 1, 1],
// [0, 0, 2, 1],
// [1, 0, 2, 1],
// [0, 2, 2, 3]
// ])
// // false