|
4 | 4 |
|
5 | 5 | 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. |
6 | 6 |
|
7 | | -**Note: |
| 7 | +**Note: |
8 | 8 | ** |
9 | 9 |
|
10 | 10 | 1. An integer point is a point that has integer coordinates. |
@@ -45,51 +45,48 @@ The input is two lists: the subroutines called and their arguments. Solution's c |
45 | 45 | 1. To get a random point, we have to locate one rectangle then pick from it |
46 | 46 | 2. Initial thought using area fails due to some rectangles have area of 0, we use count of points instead |
47 | 47 | 3. As we count through each rectangles, we accumulate the count in presum array and record total counts |
48 | | - 4. Then we generate a number, r, in \[0, totalCount\), we perform binary search to locate the rectangle that contains it \(using number in \[1, totalCount\] will keep binary search traditional\) |
| 48 | + 4. Then we generate a number, r, in \[0, total\) or better \[1, total\], this number is used to find the largest presum that are smaller or equal to r |
49 | 49 | 5. After locating the rectangle, we can either generate a point in x plus a point in y or use r generated above to get the final result |
50 | | - 6. The second way avoid extra random point generation, and the formula is x = x0 + \(r % c\), and y = y0 + \(r / c\) where r is reset to zero-based and rectangle-based by r - presum\[prev\] + 1 and c points count |
| 50 | + 6. The second way avoid extra random point generation, and the formula is x = x0 + \(r % w\), and y = y0 + \(r / w\) where r is reset to zero-based and rectangle-based by presum\[i\] - r and w is width of rectangle |
51 | 51 | 7. Time complexity O\(n\) |
52 | 52 | 8. Space complexity O\(n\) |
53 | | -2. asd |
54 | 53 |
|
55 | 54 | ### Solution |
56 | 55 |
|
57 | 56 | ```java |
58 | 57 | class Solution { |
59 | | - private int totalArea; |
| 58 | + private int total; |
60 | 59 | private int[][] rects; |
61 | | - private int[] a; |
| 60 | + private int[] presum; |
62 | 61 | private Random rand; |
63 | 62 |
|
64 | 63 | public Solution(int[][] rects) { |
65 | | - this.totalArea = 0; |
| 64 | + this.total = 0; |
66 | 65 | this.rects = rects; |
67 | | - this.a = new int[rects.length]; |
| 66 | + this.presum = new int[rects.length]; |
68 | 67 | this.rand = new Random(); |
69 | 68 | for (int i = 0; i < rects.length; i++) { |
70 | | - totalArea += getArea(rects[i]); |
71 | | - a[i] = totalArea; |
| 69 | + total += (rects[i][2] - rects[i][0] + 1) * (rects[i][3] - rects[i][1] + 1) ; |
| 70 | + presum[i] = total; |
72 | 71 | } |
73 | 72 | } |
74 | | - |
75 | | - private int getArea(int[] rect) { |
76 | | - return (rect[2] - rect[0]) * (rect[3] - rect[1]); |
77 | | - } |
78 | | - |
| 73 | + |
79 | 74 | public int[] pick() { |
80 | | - int i = binarySearch(a, rand.nextInt(totalArea) + 1); |
81 | | - int x = rand.nextInt(rects[i][2] - rects[i][0] + 1) + rects[i][0]; |
82 | | - int y = rand.nextInt(rects[i][3] - rects[i][1] + 1) + rects[i][1]; |
83 | | - return new int[] {x, y}; |
| 75 | + int r = rand.nextInt(total) + 1; |
| 76 | + int i = binarySearch(presum, r); |
| 77 | + r = presum[i] - r; |
| 78 | + int w = rects[i][2] - rects[i][0] + 1; |
| 79 | + int x = rects[i][0] + r % w; |
| 80 | + int y = rects[i][1] + r / w; |
| 81 | + return new int[]{x, y}; |
84 | 82 | } |
85 | 83 |
|
86 | 84 | private int binarySearch(int[] nums, int target) { |
87 | 85 | int lo = 0, hi = nums.length - 1; |
88 | | - while (lo <= hi) { |
| 86 | + while (lo < hi) { |
89 | 87 | int mi = lo + (hi - lo) / 2; |
90 | | - if (nums[mi] == target) return mi; |
91 | | - else if (nums[mi] < target) lo = mi + 1; |
92 | | - else hi = mi - 1; |
| 88 | + if (target > nums[mi]) lo = mi + 1; |
| 89 | + else hi = mi; |
93 | 90 | } |
94 | 91 | return lo; |
95 | 92 | } |
|
0 commit comments