通过这题学习了一下扫描线。
有两种思路。
第一种是利用点的配对加上面积来判断,比较简单不需要扫描线。
另一种是利用边的匹配。把每个矩形拆成左右两条边。
这样我们排序之后就可以从左向右扫描。
每个纵轴必然对应着几段线段并且左右两边的合并后的线段是重合的。
1 class Solution { 2 public boolean isRectangleCover(int[][] rectangles) { 3 int n = rectangles.length; 4 int line[][] = new int[n * 2][4]; 5 int idx = 0; 6 for(int i = 0; i < n; i++) { 7 line[idx++] = new int[]{rectangles[i][0], rectangles[i][1], rectangles[i][3], 1}; 8 line[idx++] = new int[]{rectangles[i][2], rectangles[i][1], rectangles[i][3], -1}; 9 } 10 Arrays.sort(line, (o1, o2) -> { 11 if(o1[0] == o2[0]) 12 return o1[1] - o2[1]; 13 return o1[0] - o2[0]; 14 }); 15 int r = 0; 16 List<int[]> l1 = new ArrayList<>(); 17 List<int[]> l2 = new ArrayList<>(); 18 for(int l = 0; l < n * 2;) { 19 while(r < 2 * n && line[r][0] == line[l][0]) 20 r++; 21 l1.clear(); 22 l2.clear(); 23 List<int[]> list; 24 for(int i = l; i < r; i++) { 25 int[] cur = line[i]; 26 list = cur[3] == 1 ? l1 : l2; 27 if(list.isEmpty()) 28 list.add(cur); 29 else { 30 int[] prev = list.get(list.size() - 1); 31 if(prev[2] > cur[1]) 32 return false; 33 else if(prev[2] == cur[1]) 34 prev[2] = cur[2]; 35 else 36 list.add(cur); 37 } 38 } 39 if(l > 0 && r < 2 * n) { 40 if(l1.size() != l2.size()) 41 return false; 42 for(int i = 0; i < l1.size(); i++) { 43 if(l1.get(i)[1] == l2.get(i)[1] && l1.get(i)[2] == l2.get(i)[2]) 44 continue; 45 return false; 46 } 47 } else 48 if(l1.size() + l2.size() != 1) 49 return false; 50 l = r; 51 } 52 return true; 53 } 54 }