#470 用Rand7()实现Rand10()
// The rand7() API is already defined for you.
// int rand7();
// @return a random integer in the range 1 to 7
class Solution {
public:
int rand10() {
while(true){
int a=rand7();
int b=rand7();
int index=b+(a-1)*7;
if(index<=40){
return 1+index%10;
}
//(1,9)
a=index-40;
b=rand7();
index=b+(a-1)*7;
if(index<=60){
return 1+index%10;
}
//(1,3)
a=index-60;
b=rand7();
index=b+(a-1)*7;
if(index<=20){
return 1+index%10;
}
}
}
};
#528.按权重随机选择
记得数学中常用的赋予数字几何意义!!!!
lower_bound(起始地址,结束地址,要查找的数值) 返回的是数值 第一个 出现的位置。
upper_bound(起始地址,结束地址,要查找的数值) 返回的是数值 最后一个 出现的位置。
class Solution {
public:
vector<int> presum;
Solution(vector<int>& w) {
if(w.size()==1){
presum.push_back(w[0]);
return;
}
presum.push_back(w[0]);
for(int i=1;i<w.size();i++){
presum.push_back(presum[i-1]+w[i]);
}
}
int pickIndex() {
int i=rand()%presum[presum.size()-1] +1;
int index=lower_bound(presum.begin(),presum.end(),i)-presum.begin();
return index;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(w);
* int param_1 = obj->pickIndex();
*/
#519.随机反转矩阵
class Solution {
public:
unordered_map<int,int> V;
int nr, nc, rem;
//c++11 random integer generation
mt19937 rng{random_device{}()};
Solution(int n_rows, int n_cols) {
nr = n_rows, nc = n_cols, rem = nr * nc;
}
vector<int> flip() {
//uniform random integer in [0, bound]
uniform_int_distribution<int> uni(0,--rem);
int r=uni(rng);
int x = V.count(r) ? V[r] : r;
V[r] = V.count(rem) ? V[rem] : rem;
return {x / nc, x % nc};
}
void reset() {
V.clear();
rem = nr*nc;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(n_rows, n_cols);
* vector<int> param_1 = obj->flip();
* obj->reset();
*/
#497.非重叠矩形中的随机点
rand()伪随机 : 感觉算法逻辑是正确的,但leetcode上会不通过,因为随机数算法不同输出和预期会不同
class Solution {
public:
vector<int> presum;
vector<vector<int>> _rects;
Solution(vector<vector<int>>& rects) {
this->_rects=rects;
if(rects.size()==1){
int h=rects[0][2]-rects[0][0]+1;
int w=rects[0][3]-rects[0][1]+1;
presum.push_back(h*w);
return;
}
int h=rects[0][2]-rects[0][0]+1;
int w=rects[0][3]-rects[0][1]+1;
presum.push_back(h*w);
for(int i=1;i<rects.size();i++){
//第i个矩形面积
h=rects[i][2]-rects[i][0]+1;
w=rects[i][3]-rects[i][1]+1;
presum.push_back(presum[i-1]+h*w);
}
}
vector<int> pick() {
int r=rand()%presum.back();
//随机选矩形
int index=lower_bound(presum.begin(),presum.end(),r)-presum.begin();
//选中矩形后随机选x,y
int newx=rand()%(_rects[index][2]-_rects[index][0]+1)+_rects[index][0];
int newy=rand()%(_rects[index][3]-_rects[index][1]+1)+_rects[index][1];
return {newx,newy};
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(rects);
* vector<int> param_1 = obj->pick();
*/
用mt19937生成器和uniform_int_distribution<int> uni;
class Solution {
public:
vector<vector<int>> rects;
vector<int> psum;
int tot = 0;
//c++11 random integer generation
mt19937 rng{random_device{}()};
uniform_int_distribution<int> uni;
Solution(vector<vector<int>> rects) {
this->rects = rects;
for (auto& x : rects) {
tot += (x[2] - x[0] + 1) * (x[3] - x[1] + 1);
psum.push_back(tot);
}
uni = uniform_int_distribution<int>{0, tot - 1};
}
vector<int> pick() {
int targ = uni(rng);
int lo = 0;
int hi = rects.size() - 1;
while (lo != hi) {
int mid = (lo + hi) / 2;
if (targ >= psum[mid]) lo = mid + 1;
else hi = mid;
}
auto& x = rects[lo];
int width = x[2] - x[0] + 1;
int height = x[3] - x[1] + 1;
int base = psum[lo] - width * height;
return {x[0] + (targ - base) % width, x[1] + (targ - base) / width};
}
};
#478.在圆内随机生成点
对于单位圆随机分别生成半径 和 角度(0-2Pi)
class Solution {
public:
double rad, xc, yc;
//c++11 random floating point number generation
mt19937 rng{random_device{}()};
uniform_real_distribution<double> uni{0, 1};
Solution(double radius, double x_center, double y_center) {
rad = radius, xc = x_center, yc = y_center;
}
vector<double> randPoint() {
double d = rad * sqrt(uni(rng));
double theta = uni(rng) * (2 * M_PI);
return {d * cos(theta) + xc, d * sin(theta) + yc};
}
};
拒接采样法:在外接矩形随机选点,在圆内就输出
class Solution {
public:
double rad, xc, yc;
//c++11 random floating point number generation
mt19937 rng{random_device{}()};
uniform_real_distribution<double> uni{0, 1};
Solution(double radius, double x_center, double y_center) {
rad = radius, xc = x_center, yc = y_center;
}
vector<double> randPoint() {
double x0 = xc - rad;
double y0 = yc - rad;
while(true) {
double xg = x0 + uni(rng) * 2 * rad;
double yg = y0 + uni(rng) * 2 * rad;
if (sqrt(pow((xg - xc), 2) + pow((yg - yc), 2)) <= rad)
return {xg, yg};
}
}
};
#710.黑名单中的随机数
这题有点难啊!!!光写个相对好理解的方法,利用哈希表进行映射
官方题解:
class Solution {
public:
unordered_map<int, int> m;
int wlen;
Solution(int n, vector<int> b) {
wlen = n - b.size();
unordered_set<int> w;
for (int i = wlen; i < n; i++) w.insert(i);
for (int x : b) w.erase(x);
auto wi = w.begin();
for (int x : b)
if (x < wlen)
m[x] = *wi++;
}
int pick() {
int k = rand() % wlen;
return m.count(k) ? m[k] : k;
}
};
自己写的:
class Solution {
public:
Solution(int N, vector<int>& blacklist) {
//计算白名单长度
wlen=N-blacklist.size();
unordered_set<int> w;
//将长度后的元素都放到白名单中
for(int i=wlen;i<N;i++){
w.insert(i);
}
//将黑名单中大于wlen的元素在白名单中剔除
for(int i=0;i<blacklist.size();i++){
if(blacklist[i]>=wlen){
w.erase(blacklist[i]);
}
}
auto iter=w.begin();
for(int i=0;i<blacklist.size();i++){
if(blacklist[i]<wlen){
hash[blacklist[i]]=*iter;
iter++;
}
}
}
int pick() {
int i=rand()%wlen;
return hash.count(i)?hash[i]:i;
}
private:
int wlen;
unordered_map<int,int> hash;
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(N, blacklist);
* int param_1 = obj->pick();
*/