难度困难234
给你一个数组
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
-105 <= xi, yi, ai, bi <= 1e5
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/perfect-rectangle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
做题结果
成功,写出扫描线方式,但是不太熟练
方法:扫描线
1. 按行扫描,按y排序,同行的先处理结束行,再处理开始行
2. 结束行:删掉头尾:如果有任何线以当前开头结尾则产生新的结尾,加到b,否则和当前已产生的结尾抵消;如果任何线以当前结尾开头则产生新的开头,添加到a,否则和当前产生的开头抵消。当前开头从去重哈希中移除
3. 开始行:添加开头不能产生重复。当前的开头结尾不断链接,最终会产生唯一的开头和唯一的结尾。如果第一次拿到开头结尾,则记录,否则判断是否相同开头结尾,是否唯一
4. 非法条件:开头重复/产生多个开头结尾/开头结尾和前面已出现行的开头结尾不一致
class Solution {
final int OPEN = 1;
final int CLOSE = 0;
public boolean isRectangleCover(int[][] rectangles) {
int n = rectangles.length;
int[][] sortLines = new int[n*2][4];
for(int i = 0; i < n; i++){
int[] rectangle=rectangles[i];
int x1 = rectangle[0];
int y1 = rectangle[1];
int x2 = rectangle[2];
int y2 = rectangle[3];
sortLines[i*2] = new int[]{OPEN,y1,x1,x2};
sortLines[i*2+1] = new int[]{CLOSE,y2,x1,x2};
}
Arrays.sort(sortLines,(a,b)->{
if(a[1]!=b[1]) return a[1]-b[1];
if(a[0]!=b[0]) return a[0]-b[0];
return a[2]-b[2];
});
int startX = Integer.MIN_VALUE;
int endX = Integer.MIN_VALUE;
Set<Integer> a = new HashSet<>();
Set<Integer> b = new HashSet<>();
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0; i < n*2; ){
int y = sortLines[i][1];
while (i<n*2&&y==sortLines[i][1]){
if(sortLines[i][0]==OPEN && map.containsKey(sortLines[i][2])) return false;
int start = sortLines[i][2];
int end = sortLines[i][3];
if(sortLines[i][0]==OPEN){
map.put(start,end);
if(b.contains(start)) b.remove(start);
else a.add(start);
if(a.contains(end)) a.remove(end);
else b.add(end);
}else{
map.remove(start);
if(a.contains(start)) a.remove(start);
else b.add(start);
if(b.contains(end)) b.remove(end);
else a.add(end);
}
++i;
}
//检查x
if(i<n*2&&map.isEmpty()) return false;
if(!map.isEmpty()){
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for(int key:a) min = key;
for(int value:b) max = value;
if(startX == Integer.MIN_VALUE){
startX = min;
endX = max;
}
if(startX != min || endX != max) return false;
if(a.size()!=1||!a.contains(min)) return false;
if(b.size()!=1||!b.contains(max)) return false;
}
}
return true;
}
}