497. Random Point in Non-overlapping Rectangles
理解
猛一看这个题,没看懂,写的时候很懵逼;
从一堆给定的non-overlapping rectangles实现randomly and uniformily 的pick()方法,每次pick的坐标要足够随机和均匀分布;
思路
1、因为rectangles的非覆盖的,用每个rectangles的area组成一个一维数组,首先从这个一维数组中取随机rand();
2、对于第1步中的随机数,查找属于哪个rectangle, 然后在查找到的rectangle中再随机坐标;
重点
1、rand()方法的使用: rand() % M;
2、rand() % M的结果范围是 [0,M-1], 双闭区间;
3、从area组成的一维数组中获得随机数,目标结果为 [1, N] , 此处的用法为 rand() % N + 1;
4、从选定的rectangle中获取随机坐标,目标结果是 [0 ~ px, 0 ~ py], 此处的用法是 rand() % (px + 1), rand() % (py + 1) ;
代码
class Solution {
public:
vector<vector<int>> rect;
vector<int> areas;
int total;
Solution(vector<vector<int>>& rects) {
rect = rects;
int n = rects.size();
areas.resize(n);
for(int i=0; i<n; i++){
int x1 = rects[i][0];
int y1 = rects[i][1];
int x2 = rects[i][2];
int y2 = rects[i][3];
if (i == 0){
areas[i] = (x2 - x1 + 1) * (y2 - y1 + 1);
}else{
areas[i] = areas[i-1] + (x2 - x1 + 1) * (y2 - y1 + 1);
}
}
total = areas[n-1];
}
vector<int> pick() {
int which = rand() % total + 1;
int i;
for(i=0; i<areas.size(); i++){
if(which <= areas[i])
break;
}
int x1 = rect[i][0];
int y1 = rect[i][1];
int x2 = rect[i][2];
int y2 = rect[i][3];
int px = rand() % (x2 - x1 + 1) + x1;
int py = rand() % (y2 - y1 + 1) + y1;
return {px, py};
}
};
优化
对于pick函数,按顺序查找which 所属的areas时,可以使用binary search进行优化,代码如下:
vector<int> pick() {
int which = rand() % total + 1;
auto it = lower_bound(areas.begin(), areas.end(), which);
int i = it - areas.begin();
// int i;
// for(i=0; i<areas.size(); i++){
// if(which <= areas[i])
// break;
// }
int x1 = rect[i][0];
int y1 = rect[i][1];
int x2 = rect[i][2];
int y2 = rect[i][3];
int px = rand() % (x2 - x1 + 1) + x1;
int py = rand() % (y2 - y1 + 1) + y1;
return {px, py};
}