持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
题目描述
给定圆的半径和圆心的位置,实现函数 randPoint ,在圆中产生均匀随机点。
实现 Solution 类:
- Solution(double radius, double x_center, double y_center) 用圆的半径 radius 和圆心的位置 (x_center, y_center) 初始化对象
- randPoint() 返回圆内的一个随机点。圆周上的一点被认为在圆内。答案作为数组返回 [x, y] 。
示例 1:
输入:
["Solution","randPoint","randPoint","randPoint"]
[[1.0, 0.0, 0.0], [], [], []]
输出: [null, [-0.02493, -0.38077], [0.82314, 0.38945], [0.36572, 0.17248]]
解释:
Solution solution = new Solution(1.0, 0.0, 0.0);
solution.randPoint ();//返回[-0.02493,-0.38077]
solution.randPoint ();//返回[0.82314,0.38945]
solution.randPoint ();//返回[0.36572,0.17248]
思路
数学题目,一开始的思路是这样的:要在圆中随机取一点,就先扩大到以圆心为中心点的正方形,此时随机取一点在数学上实现是容易的,长和宽各自在范围内随机取值即可,然后再判断这个点是否在圆内,不在圆内就重新取,这样做概率是等概率的,就是复杂度有点高,陷入这种思路后,怎么都想不到怎么直接在圆内等概率直接取一点。
看了三叶姐的题解,发现挺有意思,先分成2个维度:
- 点到圆心的距离
- 点和x轴正方向的夹角 但是这2个维度分别取随机后,组合起来确不是整体的等概率随机,因为我们是在一个平面上取的,维度1取随机,有1/2的概率取到r/2以内的值,维度2全取的情况下,此时的面积只有整体的1/4。为了解决这个问题,三叶姐在维度1取随机的时候,范围不是[0,r],而是[0,r^2],取完再做一次开方,这样就保证了在平面上是等概率的。
Java版本代码
class Solution {
private double r, x, y;
private Random random;
public Solution(double radius, double x_center, double y_center) {
r = radius;
x = x_center;
y = y_center;
random = new Random();
}
public double[] randPoint() {
double l = Math.sqrt(random.nextDouble(r*r));
double ang = random.nextDouble(2 * Math.PI);
double rx = x + l * Math.cos(ang);
double ry = y + l * Math.sin(ang);
return new double[]{rx, ry};
}
}