难度中等37
给定圆的半径和圆心的 x、y 坐标,写一个在圆中产生均匀随机点的函数 randPoint
。
说明:
输入值和输出值都将是浮点数 。
圆的半径和圆心的 x、y 坐标将作为参数传递给类的构造函数。
圆周上的点也认为是在圆中。
randPoint
返回一个包含随机点的x坐标和y坐标的大小为2的数组。
示例 1:
1 2 3 4 输入: ["Solution","randPoint","randPoint","randPoint"] [[1,0,0],[],[],[]] 输出: [null,[-0.72939,-0.65505],[-0.78502,-0.28626],[-0.83119,-0.19803]]
示例 2:
1 2 3 4 输入: ["Solution","randPoint","randPoint","randPoint"] [[10,5,-7.5],[],[],[]] 输出: [null,[11.52438,-8.33273],[2.46992,-16.21705],[11.13430,-12.42337]]
输入语法说明:
输入是两个列表:调用成员函数名和调用的参数。Solution
的构造函数有三个参数,圆的半径、圆心的 x 坐标、圆心的 y 坐标。randPoint
没有参数。输入参数是一个列表,即使参数为空,也会输入一个 [] 空列表。
C++11新特性,随机数库,不香嘛?
https://blog.csdn.net/qq_23225317/article/details/79787543
基本语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <iostream> #include <cstdlib> #include <ctime> std ::random_device rd;std ::default_random_engine e (rd()) ;std ::uniform_int_distribution<unsigned > u (0 , 9 ) ;std ::uniform_real_distribution<double > u2 (0 , 1 ) ;for (size_t i = 0 ; i < 10 ; i++) std ::cout <<u2(e)<<'\t' ; std ::cout <<"test normal distribution:\n" ;e.seed(time(0 )); std ::normal_distribution<> n (4 , 1.5 ) ;std ::vector <unsigned > vals (9 ) ;for (size_t i = 0 ; i < 250 ; i++){ unsigned v = lround(n(e)); if (v < vals.size ()) vals[v]++; } for (size_t i = 0 ; i < vals.size (); i++){ std ::cout <<i<<": " <<std ::string (vals[i], '*' )<<std ::endl ; } std ::cout <<"test normal distribution done.\n" <<std ::endl ;std ::cout <<"test bernoulli distribution:\n" ;e.seed(time(0 )); std ::bernoulli_distribution b (0.7 ) ;std ::vector <unsigned > bers (2 ) ;for (size_t i = 0 ; i < 200 ; i++){ if (b(e)) bers[1 ]++; else bers[0 ]++; } std ::cout <<"True: " <<bers[1 ]<<std ::endl ;std ::cout <<"False: " <<bers[0 ]<<std ::endl ;std ::cout <<"test bernoulli distribution done.\n" ;
某一个题解 :
相信大部分人都没有看懂,我就来通俗地解释一下吧。
确定圆内一点,需要有相对于圆心的距离r,以及相对于圆心的角度angle。
一开始的想法,我们在[0, radius]中等概率取r,在[0, 2π)中等概率取angle即可实现圆内的随机分布。
事实上,这是不对的。
在[0, 2π)中等概率取angle,相对于把一个圆分成了无数个扇形,点落在每个扇形上的概率均相等。
假设某个扇形的圆心角是theta,那么该扇形的面积是0.5 theta radius ^ 2,分布在该扇形区域上的概率是theta / 2π,只要每个扇形的圆心角相等,扇形面积就是相等的,点在扇形中也是等概率的。
在[0, radius]中等概率取r,相当于把一个圆分成了无数个环形,点落在每个环形上的概率均相等。
假设某个环形的内径是r1,外径是r2,那么该环形的面积是π * (r2 ^ 2 - r1 ^ 2)。可见每个环形的面积是不一样的,显然每个环形上的点密度是不一样的。这样做会造成靠近圆心的点分布比较密集,远离圆心的点分布比较稀疏。
那么,如何取r使得点落在圆内任意区域的概率均相等呢?这样做显然会使得落在每个环形上的概率均不同,且环形面积较大的概率高,环形面积较小的概率小。
根据环形面积的计算公式:π * (r2 ^ 2 - r1 ^ 2),落在该环形面积上的概率应为(r2 ^ 2 - r1 ^ 2) / (radius ^ 2)。
在[0, radius]中如何分布概率密度函数f(x),可以使得f(x)其在[r1, r2]上的积分值为(r2 ^ 2 - r1 ^ 2) / (radius ^ 2)呢?
取f(x) = 2x / (radius ^ 2)可以满足上述条件,即半径r在[0, radius]上的概率密度函数应为f(x) = 2x / (radius ^ 2),故只需要在[0, radius ^ 2]范围内等概率取r ^ 2,再开根号即得r值。(求一下导数即可,x ^ 2的导数是2x)
时间复杂度是和空间复杂度均是O(1)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Solution {private : double radius; double x_center,y_center; double _2pi; public : Solution(double radius, double x_center, double y_center) { this ->radius=radius; this ->x_center=x_center; this ->y_center=y_center; this ->_2pi=acos (-1 )*2 ; } vector <double > randPoint () { vector <double >result; if (radius>0 ){ random_device rd; default_random_engine e (rd()) ; uniform_real_distribution<double >u1(0 ,radius*radius); uniform_real_distribution<double >u2(0 ,_2pi); double r=sqrt (u1(e)); double theta=u2(e); double x=x_center+r*cos (theta); double y=y_center+r*sin (theta); result.push_back(x); result.push_back(y); } return result; } };