leetcode497 - Random Point in Non-overlapping Rectangles - medium
Given a list of non-overlapping axis-aligned rectangles rects, write a function pick which randomly and uniformily picks an integer point in the space covered by the rectangles.
Note:
1. An integer point is a point that has integer coordinates.
2. A point on the perimeter of a rectangle is included in the space covered by the rectangles.
3. ith rectangle = rects[i] = [x1,y1,x2,y2], where [x1, y1] are the integer coordinates of the bottom-left corner, and [x2, y2] are the integer coordinates of the top-right corner.
4. length and width of each rectangle does not exceed 2000.
5. 1 <= rects.length <= 100
6. pick return a point as an array of integer coordinates [p_x, p_y]
7. pick is called at most 10000 times.
Example 1:
Input:
["Solution","pick","pick","pick"]
[[[[1,1,5,5]]],[],[],[]]
Output:
[null,[4,1],[4,1],[3,3]]
Example 2:
Input:
["Solution","pick","pick","pick","pick","pick"]
[[[[-2,-2,-1,-1],[1,0,3,0]]],[],[],[],[],[]]
Output:
[null,[-1,-2],[2,0],[-2,-1],[3,0],[-2,-2]]
1.trivial solution. 一开始建立好所有可能的点,然后用O(1) pick其中一个点。 但不现实,如果给的一个长方形面积特别大,那你一开始建立所有点用的memory就爆炸了。
2.先根据面积作为权重,按概率选到长方形。之后在这个长方形的范围内随机选x和y,输出。
本题相关:Random Pick with Weight: https://www.cnblogs.com/jasminemzy/p/9741839.html
实现:
class Solution { private int[][] rects; private Random rd; private int[] sum; private int total; public Solution(int[][] rects) { this.rects = rects; this.rd = new Random(); int[] weight = new int[rects.length]; for (int i = 0; i < rects.length; i++) { weight[i] = (rects[i][2] - rects[i][0] + 1) * (rects[i][3] - rects[i][1] + 1); } this.sum = new int[weight.length]; this.total = 0; for (int i = 0; i < sum.length; i++) { total += weight[i]; sum[i] = total; } } public int[] pick() { int[] rect = rects[pickRect()]; int x = rect[0] + rd.nextInt(rect[2] - rect[0] + 1); int y = rect[1] + rd.nextInt(rect[3] - rect[1] + 1); return new int[] {x, y}; } private int pickRect() { int target = rd.nextInt(total); int i = 0, j = sum.length - 1; while (i < j) { int mid = (i + j) / 2; if (sum[mid] > target) { j = mid; } else { i = mid + 1; } } return i; } } /** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(rects); * int[] param_1 = obj.pick(); */