Leetcode: Perfect Rectangle
This question is asked in Apple, Google, and Uber.
Given an array rectangles where rectangles [xi, yi, ai, bi] represents an axis-aligned rectangle. The bottom left of the rectangle is (xi, yi) and the top right point of the rectangle is (ai, bi). No rectangles are allowed to overlap each other.
For example, rectangles = [[1,1,3,3],[3,1,4,2],[3,2,4,4],[1,3,2,4],[2,3,3,4]] fits as a rectangle because all of the 5 rectangles cover a rectangular region. However, in the case of overlapping rectangle, rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[2,2,4,4]] fails to produce result as [1, 1, 3, 3,] and [2, 2, 4, 4] overlap each other. From this we can conclude that a rectangle will overlap each other if any data point x and y value is between the data point of the first rectangle and the data point of the second rectangle.
So the right answer must satisfy 2 conditions:
1. the large rectangle area should be equal to the sum of all the small rectangles.
2. Count of all the points should be even and the count of all of the 4 corner points should be 1. Here's why:
A point can cover one point (total of 2 as an edge) or 3 other points (total of 4 points as a corner). This image is very useful in the terms of understanding the algorithm:
A fast solution is to store a point object in set and initialize it as a separate class. Here's the final code:
class Solution {
static class Point {
int x;
int y;
//x and y coordinates
Point(int x, int y) {
this.x = x;
this.y = y;
}
//see if the point equals object
public boolean equals(Object o) {
if(o instanceof Point) {
Point p = (Point) o;
return this.x == p.x && this.y = p.y;
}
return false;
}
//override hash function
public int hashCode() {
int code = 1;
code = code * 31 + x;
code = code * 31 + y;
return code;
}
}
public boolean isRectangleCover(int[][] rectangles) {
//base null condition
if(rectangles == null || rectangles.length == 0) return false;
//set values to polar opposites of direction we reach
int x1 = Integer.MAX_VALUE;
int y1 = Integer.MAX_VALUE;
int x2 = Integer.MIN_VALUE;
int y2 = Integer.MIN_VALUE;
int area = 0;
//initialize hashset
Set<Point> set = new HashSet<>();
//for all the rectangles
for(int[] rec : rectangles) {
//calculate the area
area += (rec[2] - rec[0]) * (rec[3] - rec[1]);
//update all of the edge points
x1 = Math.min(x1, rec[0]);
y1 = Math.min(y1, rec[1]);
x2 = Math.max(x2, rec[2]);
y2 = Math.max(y2, rec[3]);
//remove from the set if the set already contains the particular point
Point p1 = new Point(rec[0], rec[1]);
if(!set.add(p1)) set.remove(p1);
Point p2 = new Point(rec[0], rec[3]);
if(!set.add(p2)) set.remove(p2);
Point p3 = new Point(rec[2], rec[3]);
if(!set.add(p3)) set.remove(p3);
Point p4 = new Point(rec[2], rec[1]);
if(!set.add(p4)) set.remove(p4);
}
//now we make sure the set contains all the edge points
if(set.size() != 4 || !set.contains(new Point(x1, y1))|| !set.contains(new Point(x1, y2)) || set.contains(new Point(x2, y2)) || set.contains(new Point(x2, y1))){
return false;
}
//confirm the area is the same as covered in the edge points.
return area == (x2 - x1) * (y2 - y1);
}
}


Comments
Post a Comment