题目
给你一个数组 rectangles ,其中 rectangles[i] = [xi, yi, ai, bi] 表示一个坐标轴平行的矩形。这个矩形的左下顶点是 (xi, yi) ,右上顶点是 (ai, bi) 。
如果所有矩形一起精确覆盖了某个矩形区域,则返回 true ;否则,返回 false 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/perfect-rectangle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码
class Solution {
public boolean isRectangleCover(int[][] rectangles) {
int X1 = Integer.MAX_VALUE, Y1 = Integer.MAX_VALUE;//左下角最小值
int X2 = Integer.MIN_VALUE, Y2 = Integer.MIN_VALUE;//右上角最大值
HashSet<Integer> points = new HashSet<>();//记录点信息
long act_area = 0;
for (int i = 0; i < rectangles.length; i++) {
int x1 = rectangles[i][0], y1 = rectangles[i][1];
int x2 = rectangles[i][2], y2 = rectangles[i][3];
//计算完美矩形的理论顶点坐标
X1 = Math.min(X1, x1);
Y1 = Math.min(Y1, y1);
X2 = Math.max(X2, x2);
Y2 = Math.max(Y2, y2);
//累加小矩形的面积
act_area += (long) (x2 - x1) * (y2 - y1);
//记录最终形成的图形中的顶点
int p1=key(x1,y1);
int p2=key(x1,y2);
int p3=key(x2,y1);
int p4=key(x2,y2);
if (points.contains(p1)) points.remove(p1);
else points.add(p1);
if (points.contains(p2)) points.remove(p2);
else points.add(p2);
if (points.contains(p3)) points.remove(p3);
else points.add(p3);
if (points.contains(p4)) points.remove(p4);
else points.add(p4);
}
//判断面积是否相同
long expected_erea = (long) (X2 - X1) * (Y2 - Y1);
if (act_area != expected_erea) return false;//面积不相等
//判断最终留下的顶点个数是否为 4
if (points.size() != 4) return false;
//判断留下的 4 个顶点是否是完美矩形的顶点
if (!points.contains(key(X1, Y1))) return false;
if (!points.contains(key(X1, Y2))) return false;
if (!points.contains(key(X2, Y1))) return false;
if (!points.contains(key(X2, Y2))) return false;
return true;
}
private int key(int x, int y){
// 二维坐标转一维,方便比较
// 100000007是随便取的一个大质数
// 这里即使溢出了也没什么问题
return x*100000007 +y;
}
}
要点
- 对于完美矩形的判断,需要从坐标和面积角度进行约束
- 判断面积,通过完美矩形的理论坐标计算出一个理论面积,然后和 rectangles 中小矩形的实际面积和做对比。
- 判断顶点,points 集合中应该只剩下 4 个顶点且剩下的顶点必须都是完美矩形的理论顶点。
- 注意在java中不能通过数组作为key,数组作为key使用地址进行比较,需要自定义key规则