当前位置:网站首页>【Leetcode】478. Generate Random Point in a Circle(配数学证明)
【Leetcode】478. Generate Random Point in a Circle(配数学证明)
2022-08-01 23:47:00 【记录算法题解】
题目地址:
https://leetcode.com/problems/generate-random-point-in-a-circle/
给定二维圆的圆心坐标 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)及其半径 r r r,要求等概率产生在圆内的点的坐标。圆周上的点也视为有效。
法1:拒绝采样法。只需要能等概率产生单位圆中的随机点即可,可以用拒绝采样法。产生 [ − 1 , 1 ] 2 [-1,1]^2 [−1,1]2中的随机点是简单的,每次产生了 ( x , y ) (x,y) (x,y)之后,只当 x 2 + y 2 ≤ 1 x^2+y^2\le 1 x2+y2≤1的时候才停止采样,那么由于每次采样在范围内的概率 π 4 < 1 \frac{\pi}{4}<1 4π<1,采样次数服从几何分布,所以采样以概率 1 1 1停止,设采样停止这个事件为 A A A,设圆内有个小面积 S S S,则 P ( ( x , y ) ∈ S ∣ A ) = P ( ( x , y ) ∈ S ) P((x,y)\in S|A)=P((x,y)\in S) P((x,y)∈S∣A)=P((x,y)∈S)即为 S S S的面积,从而满足题意。采样次数的期望为 4 π \frac{4}{\pi} π4。代码如下:
import java.util.Random;
public class Solution {
Random random;
double xc, yc, r, x, y;
public Solution(double radius, double x_center, double y_center) {
random = new Random();
xc = x_center;
yc = y_center;
r = radius;
}
public double[] randPoint() {
do {
generate();
} while (!check(x, y));
return new double[]{
xc + r * x, yc + r * y};
}
void generate() {
x = random.nextDouble() * 2 - 1;
y = random.nextDouble() * 2 - 1;
}
boolean check(double x, double y) {
return x * x + y * y <= 1.0;
}
}
randPoint时空复杂度 O ( 1 ) O(1) O(1)。
法2:设 ( R , Θ ) (R, \Theta) (R,Θ)满足 [ 0 , 1 ] × [ 0 , 2 π ] [0, 1]\times [0,2\pi] [0,1]×[0,2π]的均匀分布,则 ( X , Y ) = ( R cos Θ , R sin Θ ) (X,Y)=(\sqrt R\cos\Theta, \sqrt R\sin\Theta) (X,Y)=(RcosΘ,RsinΘ)满足单位圆的均匀分布。
证明:设 ( x ( r , θ ) , y ( r , θ ) ) = ( r cos θ , r sin θ ) (x(r,\theta), y(r,\theta))=(\sqrt r\cos\theta, \sqrt r\sin\theta) (x(r,θ),y(r,θ))=(rcosθ,rsinθ),设 ( X , Y ) (X,Y) (X,Y)的密度函数为 p ( x , y ) p(x,y) p(x,y),那么面积微元 p ( x , y ) d x d y = p ( r cos θ , r sin θ ) ∣ J ∣ d r d θ = 1 2 π d r d θ p(x, y)dxdy=p(r\cos\theta, r\sin\theta)|J|drd\theta=\frac{1}{2\pi}drd\theta p(x,y)dxdy=p(rcosθ,rsinθ)∣J∣drdθ=2π1drdθ其中 J J J是Jacobi矩阵, J = [ ∂ x ∂ r ∂ x ∂ θ ∂ y ∂ r ∂ y ∂ θ ] = [ cos θ 2 r − r sin θ sin θ 2 r r cos θ ] J = \begin{bmatrix} \dfrac{\partial x}{\partial r} & \dfrac{\partial x}{\partial \theta}\\ \dfrac{\partial y}{\partial r} & \dfrac{\partial y}{\partial \theta}\end{bmatrix}= \begin{bmatrix} \dfrac{\cos\theta}{2\sqrt r} & -\sqrt r\sin\theta\\ \dfrac{\sin\theta}{2\sqrt r} & \sqrt r\cos\theta \end{bmatrix} J=⎣⎡∂r∂x∂r∂y∂θ∂x∂θ∂y⎦⎤=⎣⎡2rcosθ2rsinθ−rsinθrcosθ⎦⎤ ∣ J ∣ = 1 2 |J|=\frac{1}{2} ∣J∣=21,从而 p ( x , y ) = 1 π p(x,y)=\frac{1}{\pi} p(x,y)=π1,满足题意。代码如下:
import java.util.Random;
public class Solution {
Random random;
double r, x, y;
public Solution(double radius, double x_center, double y_center) {
random = new Random();
this.r = radius;
this.x = x_center;
this.y = y_center;
}
public double[] randPoint() {
double theta = random.nextDouble() * 2 * Math.PI;
double randomR = r * Math.sqrt(random.nextDouble());
return new double[]{
x + randomR * Math.cos(theta), y + randomR * Math.sin(theta)};
}
}
randPoint时空复杂度 O ( 1 ) O(1) O(1)。
法1:C++:
class Solution {
public:
double r, xc, yc, x, y;
Solution(double radius, double x_center, double y_center) {
r = radius;
xc = x_center;
yc = y_center;
}
vector<double> randPoint() {
double x, y;
do {
x = (double)rand() / RAND_MAX * 2 - 1;
y = (double)rand() / RAND_MAX * 2 - 1;
} while (x * x + y * y > 1);
return {
xc + x * r, yc + y * r};
}
};
时空复杂度一样。
法2:C++(C++里的 π \pi π可以由 arccos − 1 \arccos-1 arccos−1得到):
class Solution {
public:
double r, xc, yc, x, y;
Solution(double radius, double x_center, double y_center) {
r = radius;
xc = x_center;
yc = y_center;
}
vector<double> randPoint() {
double radius = sqrt((double)rand() / RAND_MAX) * r;
double theta = ((double)rand() / RAND_MAX) * 2 * acos(-1);
return {
xc + radius * cos(theta), yc + radius * sin(theta)};
}
};
时空复杂度一样。
边栏推荐
- DRF generating serialization class code
- oozie startup error on cdh's hue, Cannot allocate containers as requested resource is greater than maximum allowed
- How do programmers solve online problems gracefully?
- What can be done to make this SQL into a dangerous SQL?
- Special characters & escapes in bat
- 使用Ganache、web3.js和remix在私有链上部署并调用合约
- LocalDateTime转为Date类型
- @Transactional注解在类上还是接口上使用,哪种方式更好?
- Leetcode 129求根节点到叶节点数字之和、104二叉树的最大深度、8字符串转换整数(atoi)、82删除排序链表中的重复元素II、204二分查找、94二叉树的中序遍历、144二叉树的前序遍历
- Docker搭建Mysql主从复制
猜你喜欢
随机推荐
Architecture basic concept and nature of architecture
DRF generating serialization class code
Thymeleaf简介
Chapter 12 End-User Task As Shell Scripts
Programmer is still short of objects? A new one is enough
2022 6th Strong Net Cup Part WP
20220725 Information update
【图像融合】基于加权和金字塔实现图像融合附matlab代码
The third chapter of the imitation cattle network project: develop the core functions of the community (detailed steps and ideas)
GIF制作-灰常简单的一键动图工具
Check if point is inside rectangle
Additional Features for Scripting
A brief analysis of mobile APP security testing in software testing, shared by a third-party software testing agency in Beijing
一道golang中关于iota的面试题
工件SSMwar exploded 部署工件时出错。请参阅服务器日志了解详细信息
cdh的hue上oozie启动报错,Cannot allocate containers as requested resource is greater than maximum allowed
Avoid hidden text when loading fonts
Share an interface test project (very worth practicing)
WEB安全基础 - - - XRAY使用
【MySQL篇】初识数据库









