具体思想:
随即问题,统计点,然后直接随机抽一个,算是哪个矩阵的几行几列。
前缀和二分有个问题;
首先,对于n个点,随机数生成的是0~n-1的一个值,实际寻找的时候一定要+1;
例如,对于生成随机数4,其实是要求第五个点;
对于,0,1,4,8;
如果按照4来找,会找到第二个矩阵,实际上要找第五个点,应该找到第三个矩阵;
同理,后序在该矩阵里,应该找5-4=1,第一个点;
但是后续算坐标偏移,又应该剪1,麻烦的一笔;
具体代码:
普通思路:
class Solution {
public:
Solution(vector<vector<int>>& rects) {
n=0;
rects_=rects;
for(auto& vec:rects){
int temp=points_cnt(vec);
n+=temp;
pn.push_back(temp);
}
}
vector<int> pick() {
int ran=rand()%n;
int index=-1;
for(int i=0;i<pn.size();i++){
if(ran>=pn[i]){
ran-=pn[i];
continue;
}
index=i;
break;
}
//找到第几个矩阵;
int col=rects_[index][2]-rects_[index][0]+1;
int r=ran%col,c=ran/col;
return {r+rects_[index][0],c+rects_[index][1]};
}
int points_cnt(vector<int>& rect){
return (rect[2]-rect[0]+1)*(rect[3]-rect[1]+1);
}
private:
int n;
vector<int> pn;
vector<vector<int>> rects_;
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(rects);
* vector<int> param_1 = obj->pick();
*/
二分思路:
using ll=long long;
class Solution {
public:
Solution(vector<vector<int>>& rects) {
n=0;
rects_=rects;
arr.push_back(0);
int total=0;
for(auto& vec:rects){
total+=points_cnt(vec);
arr.push_back(total);
}
n=total;
}
//1,3,6
//4,10
vector<int> pick() {
//n=*arr.rbegin();
int ran=rand()%n+1;
int l=0;
int r=arr.size()-1;
while(l<r){
int mid=l+(r-l)/2;
if(arr[mid]>=ran){
r=mid;
}else{
l=mid+1;
}
}//找到第几个矩阵;
l=r-1;
ran=ran-arr[l]-1;
int col=rects_[l][2]-rects_[l][0]+1;
int ro=ran%col,co=ran/col;
return {ro+rects_[l][0],co+rects_[l][1]};
}
ll points_cnt(vector<int>& rect){
return ll(rect[2]-rect[0]+1)*ll(rect[3]-rect[1]+1);
}
private:
int n;
vector<ll> arr;
vector<vector<int>> rects_;
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(rects);
* vector<int> param_1 = obj->pick();
*/