497. Random Point in Non-overlapping Rectangles #
Problem #
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:
- An integer point is a point that has integer coordinates.
- A point on the perimeter of a rectangle is included in the space covered by the rectangles.
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.- length and width of each rectangle does not exceed
2000. 1 <= rects.length <= 100pickreturn a point as an array of integer coordinates[p_x, p_y]pickis called at most10000times.
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]]
Explanation of Input Syntax:
The input is two lists: the subroutines called and their arguments. Solution's constructor has one argument, the array of rectangles rects. pick has no arguments. Arguments are always wrapped with a list, even if there aren’t any.
Problem Summary #
Given a list of non-overlapping axis-aligned rectangles rects, write a function pick to randomly and uniformly select an integer point in the space covered by the rectangles.
Notes:
- An integer point is a point with integer coordinates.
- Points on the perimeter of a rectangle are included in the space covered by the rectangle.
- The 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.
- The length and width of each rectangle do not exceed 2000.
- 1 <= rects.length <= 100
- pick returns a point in the form of an array of integer coordinates [p_x, p_y].
- pick is called at most 10000 times.
Explanation of Input Syntax:
The input is two lists: the subroutines called and their arguments. Solution’s constructor has one argument, the array of rectangles rects. pick has no arguments. Arguments are always wrapped in a list, even if there aren’t any.
Solution Approach #
- Given a list of non-overlapping axis-aligned rectangles, each rectangle is represented by the coordinates of its bottom-left and top-right corners. The requirement is for
pick()to randomly and uniformly select an integer point in the space covered by the rectangles. - This problem is a variant of Problem 528. In this problem, the weight is the area. Select a rectangle by weight (area), then randomly select a point from that rectangle. The idea and code are the same as in Problem 528.
Code #
package leetcode
import "math/rand"
// Solution497 define
type Solution497 struct {
rects [][]int
arr []int
}
// Constructor497 define
func Constructor497(rects [][]int) Solution497 {
s := Solution497{
rects: rects,
arr: make([]int, len(rects)),
}
for i := 0; i < len(rects); i++ {
area := (rects[i][2] - rects[i][0] + 1) * (rects[i][3] - rects[i][1] + 1)
if area < 0 {
area = -area
}
if i == 0 {
s.arr[0] = area
} else {
s.arr[i] = s.arr[i-1] + area
}
}
return s
}
// Pick define
func (so *Solution497) Pick() []int {
r := rand.Int() % so.arr[len(so.arr)-1]
//get rectangle first
low, high, index := 0, len(so.arr)-1, -1
for low <= high {
mid := low + (high-low)>>1
if so.arr[mid] > r {
if mid == 0 || so.arr[mid-1] <= r {
index = mid
break
}
high = mid - 1
} else {
low = mid + 1
}
}
if index == -1 {
index = low
}
if index > 0 {
r = r - so.arr[index-1]
}
length := so.rects[index][2] - so.rects[index][0]
return []int{so.rects[index][0] + r%(length+1), so.rects[index][1] + r/(length+1)}
}
/**
* Your Solution object will be instantiated and called as such:
* obj := Constructor(rects);
* param_1 := obj.Pick();
*/