Problem
You are given an array of non-overlapping axis-aligned rectangles rects where rects[i] = [ai, bi, xi, yi] indicates that (ai, bi) is the bottom-left corner point of the ith rectangle and (xi, yi) is the top-right corner point of the ith rectangle. Design an algorithm to pick a random integer point inside the space covered by one of the given rectangles. A point on the perimeter of a rectangle is included in the space covered by the rectangle.
Any integer point inside the space covered by one of the given rectangles should be equally likely to be returned.
Note that an integer point is a point that has integer coordinates.
Implement the Solution class:
Solution(int[][] rects)Initializes the object with the given rectanglesrects.int[] pick()Returns a random integer point[u, v]inside the space covered by one of the given rectangles.
Example 1:

Input
["Solution", "pick", "pick", "pick", "pick", "pick"]
[[[[-2, -2, 1, 1], [2, 2, 4, 6]]], [], [], [], [], []]
Output
[null, [1, -2], [1, -1], [-1, -2], [-2, -2], [0, 0]]
Explanation
Solution solution = new Solution([[-2, -2, 1, 1], [2, 2, 4, 6]]);
solution.pick(); // return [1, -2]
solution.pick(); // return [1, -1]
solution.pick(); // return [-1, -2]
solution.pick(); // return [-2, -2]
solution.pick(); // return [0, 0]
Constraints:
1 <= rects.length <= 100rects[i].length == 4-10^9 <= ai < xi <= 10^9-10^9 <= bi < yi <= 10^9xi - ai <= 2000yi - bi <= 2000All the rectangles do not overlap.
At most
10^4calls will be made topick.
Solution (Java)
class Solution {
private final int[] weights;
private final int[][] rects;
private final Random random;
public Solution(int[][] rects) {
this.weights = new int[rects.length];
this.rects = rects;
this.random = new Random();
for (int i = 0; i < rects.length; i++) {
int[] rect = rects[i];
int count = (1 + rect[2] - rect[0]) * (1 + rect[3] - rect[1]);
weights[i] = (i == 0 ? 0 : weights[i - 1]) + count;
}
}
public int[] pick() {
int picked = 1 + random.nextInt(weights[weights.length - 1]);
int idx = findGreaterOrEqual(picked);
return getRandomPoint(idx);
}
private int findGreaterOrEqual(int target) {
int left = 0;
int right = weights.length - 1;
while (left + 1 < right) {
int mid = left + (right - left) / 2;
if (weights[mid] >= target) {
right = mid;
} else {
left = mid + 1;
}
}
return weights[left] >= target ? left : right;
}
private int[] getRandomPoint(int idx) {
int[] r = rects[idx];
int left = r[0];
int right = r[2];
int bot = r[1];
int top = r[3];
return new int[] {
left + random.nextInt(right - left + 1), bot + random.nextInt(top - bot + 1)
};
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(rects);
* int[] param_1 = obj.pick();
*/
Explain:
nope.
Complexity:
- Time complexity : O(n).
- Space complexity : O(n).