LeetCode-Perfect Rectangle

LiBlog發表於2016-09-01

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));
    }

}

 

 

 

 

相關文章