Description
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 <= 100
- pick return a point as an array of integer coordinates [p_x, p_y]
- 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]]
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.
分析
题目的意思是:给定很多非重叠矩形,随机从这些矩形中取出点。我一开始以为的随机就是random,原来是所有的点被选择的概率相等,所以需要设置一个weight数组表示的是sum数组的累加和,这是为了让选择每个点都有随机性,在pick的时候随机选出x,找出x落在的w中的最近区间,得到该区间的索引,然后在对应的rect中选择出一个点输出就行了。这样就能进行随机的输出点了。
比如:
[[[[-2,-2,-1,-1],[1,0,3,0]]],[],[],[],[],[]]
sum里面的值为[4,3]
w里面的值为[4,7]
随机选一个x比如是3,二分法进行w的数的比较,发现3落在的索引位置为0
取出第0个位置的rect,随机选一个点就行了
代码
class Solution:
def __init__(self, rects: List[List[int]]):
self.sum=[(x2-x1+1)*(y2-y1+1) for x1,y1,x2,y2 in rects]
self.w=[self.sum[0]]
for i in range(1,len(self.sum)):
self.w.append(self.w[-1]+self.sum[i])
self.rects=rects
def pick(self) -> List[int]:
l=0
h=len(self.w)-1
x=random.randint(0,self.w[-1]-1)
while(l<h):
mid=l+(h-l)//2
if(self.w[mid]>x):
h=mid
else:
l=mid+1
x1,y1,x2,y2=self.rects[l]
return [random.randint(x1,x2),random.randint(y1,y2)]
# Your Solution object will be instantiated and called as such:
# obj = Solution(rects)
# param_1 = obj.pick()
参考文献
[LeetCode] [Python] Short solution with binary search, explained