LeetCode-Perfect Rectangle
Given N axis-aligned rectangles where N > 0, determine if they all together form an exact cover of a rectangular region.
Each rectangle is represented as a bottom-left point and a top-right point. For example, a unit square is represented as [1,1,2,2]. (coordinate of bottom-left point is (1, 1) and top-right point is (2, 2)).
Example 1:
rectangles = [ [1,1,3,3], [3,1,4,2], [3,2,4,4], [1,3,2,4], [2,3,3,4] ] Return true. All 5 rectangles together form an exact cover of a rectangular region.
Example 2:
rectangles = [ [1,1,2,3], [1,3,2,4], [3,1,4,2], [3,2,4,4] ] Return false. Because there is a gap between the two rectangular regions.
Example 3:
rectangles = [ [1,1,3,3], [3,1,4,2], [1,3,2,4], [3,2,4,4] ] Return false. Because there is a gap in the top center.
Example 4:
rectangles = [ [1,1,3,3], [3,1,4,2], [1,3,2,4], [2,2,4,4] ] Return false. Because two of the rectangles overlap with each other.
Analysis:
We do not need to worry about how to arrange those rectangles to use some algorithm checking them. The key point here is that:
For each point being a corner of any rectangle, it should appear even times except the 4 corners of the large rectangle. So we can put those points into a hash map and remove them if they appear one more time.
At the end, we should only get 4 points. To prevent overlapping, i.e., two rectangles overlap at the same corner, we should further record which corner a point A belongs to in Rectangle X.
At last, we should also keep track of the total covered area, which should equals to the area of the large rectangle.
Solution:
idea got from this post:
https://discuss.leetcode.com/topic/56349/o-n-java-solution-with-213-ms-runtime
Improved:
1. Hash code
2. Check whether index of point A in the hash map is the same with a point B (suppose A == B), if yes, the overlapping detected, return false.
3. Directly contructs 4 points in an array.
Runtime is improved from O(200ms) to O(60ms).
public class Solution { class Point { int x; int y; int index; public Point(int xx, int yy, int i) { x = xx; y = yy; index = i; } public boolean equals(Object obj) { if (obj instanceof Point) { Point that = (Point) obj; return that.x == x && that.y == y; } return false; } public int hashCode() { return new Integer(x).hashCode() * 31 + new Integer(y).hashCode(); } } public boolean isRectangleCover(int[][] rectangles) { if (rectangles.length == 0) return false; HashMap<Point, Integer> pMap = new HashMap<Point, Integer>(); int area = 0; int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = -1, maxY = -1; for (int[] rect : rectangles) { Point[] points = new Point[4]; points[0] = new Point(rect[0], rect[1], 1); points[1] = new Point(rect[0], rect[3], 2); points[2] = new Point(rect[2], rect[3], 3); points[3] = new Point(rect[2], rect[1], 4); area += (rect[2] - rect[0]) * (rect[3] - rect[1]); minX = Math.min(minX, rect[0]); minY = Math.min(minY, rect[1]); maxX = Math.max(maxX, rect[2]); maxY = Math.max(maxY, rect[3]); for (Point p : points) if (pMap.containsKey(p)) { // The existing point should not have the same index with // @p, otherwise, it means that there is overlapping. if (pMap.get(p) != p.index) { // The point in the map is removed by the same point of // another rectangle. pMap.remove(p); } else { return false; } } else { pMap.put(p, p.index); } } return (pMap.size() == 4) && (area == (maxX - minX) * (maxY - minY)); } }