当前位置:   article > 正文

拒绝采样 Rejection Sampling

rejection sample

2018-12-09 16:40:30

一、使用Rand7()来生成Rand10()

问题描述:

问题求解:

这个问题字节跳动算法岗面试有问到类似的,有rand6,求rand8,我想了好久,最后给了一个特殊解法,就进行三次,每次取前三个数和后三个数的概率相等为1 / 2,那么最后需要得到的概率是1 / 8,就可以通过取三次得到。问题就转变成了映射的问题,当然映射的方式是很简单的,类似二进制的方法,很容易就可以进行映射。

但是,上述的解法在本题中是没有办法使用的,就需要更通用的解法,说实话,之前也没有做过Rejection Sampling标签下的题目,这个问题的通用解法就是使用拒绝采样的算法来进行解决。

首先我们肯定是需要对原空间进行扩充的,因为原空间的大小比生成空间的大小要小。

我其实最初想到的也是两次求rand7(),然后直接求和,但是很显然的这样得到的解空间中的1 - 10是不平均分配的,即使通过对10取余 + 1也不能得到等概率的解。

当然还有人可能会想通过求乘积的方式来扩充空间,可惜的是这样也是非等概率的,具体可以见下图:

那么怎么样才能得到等概率的呢?其实,我们只需要对两次取得的各个可能的数进行编号,每个编号不就是等可能的么?

由于编号的总长度大于10的倍数,后面的49 - 40 = 9个数字就需要抛弃掉。通过这种方式,我们就可以等概率的生成1 - 10这10个整数。

  1. /**
  2. * The rand7() API is already defined in the parent class SolBase.
  3. * public int rand7();
  4. * @return a random integer in the range 1 to 7
  5. */
  6. class Solution extends SolBase {
  7. public int rand10() {
  8. int res = Integer.MAX_VALUE;
  9. while (res >= 40) {
  10. res = 7 * (rand7() - 1) + rand7() - 1;
  11. }
  12. return res % 10 + 1;
  13. }
  14. }

 

二、Generate Random Point in a Circle

问题描述:

问题求解:

本题最直观的解法就是拒绝采样了,解法的流程是生成一个圆的外接矩形框,随机产生矩形框中的数字,如果在圆内,那么就输出,否则拒绝采样,重新生成一遍。

本题中有个问题就是题目描述中说边界的点是算在圆中的,但是Java中的随机数如Math.random(),或者Random rand.nextDouble()产生的随机数都在[0, 1.0)前开后闭,这也就意味着某些圆上的点是没有办法取到的。

这个问题呢,可以这么理解,纵然有某些圆上的点是没有办法取到的,但是并不影响最终的结果,因为圆中的点理论上来说是有无数个的,因此对于某个单独的点其生成的概率是为0 的。

  1. class Solution {
  2. double r, x, y;
  3. public Solution(double radius, double x_center, double y_center) {
  4. r = radius;
  5. x = x_center;
  6. y = y_center;
  7. }
  8. public double[] randPoint() {
  9. Random rand = new Random();
  10. Double nx = x - r + rand.nextDouble() * 2 * r;
  11. double ny = y - r + rand.nextDouble() * 2 * r;
  12. double r2 = r * r;
  13. while(dis(nx, ny) >= r2){
  14. nx = x - r + rand.nextDouble() * 2 * r;
  15. ny = y - r + rand.nextDouble() * 2 * r;
  16. }
  17. return new double[]{nx, ny};
  18. }
  19. // it returns the square of the distance between the point and the center;
  20. double dis(double nx, double ny){
  21. return (nx - x) * (nx - x) + (ny - y) * (ny - y);
  22. }
  23. }

 

转载于:https://www.cnblogs.com/hyserendipity/p/10091978.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/987119
推荐阅读
相关标签
  

闽ICP备14008679号