给定圆的半径和圆心的位置,实现函数 randPoint ,在圆中产生均匀随机点。
持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
实现 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]
拒绝采样
拒绝采样的意思是说:我们在一个更大的范围内生成随机数,并拒绝掉那些不在题目给定范围内的随机数,此时保留下来的随机数都是在范围内的。为了在一个半径为 R 的圆中生成均匀随机点,我们可以使用一个边长为 2R 的正方形覆盖住圆,并在正方形内生成均匀随机点,此时就只需要对于横坐标和纵坐标分别生成一个随机数即可。
由于正方形的面积为 ,圆的面积为 ,因此在正方形中随机生成的点,落在圆内的概率为 ,期望的生成次数为 。
在正方形中生成点时(正方形中心的坐标简记为原点),如果我们在 的范围内生成随机数,那么是无法生成到横坐标或纵坐标恰好为 R 的点,对应到圆上时,会有圆周上与正方形边相切的两个点无法随机到。我们可以在生成时稍微提高右边界(例如 ,其中 是一个很小的常数,例如 ,或者直接忽略这两个点,因为它们的勒贝格测度为零。
var Solution = function(radius, x_center, y_center) {
this.xc = x_center;
this.yc = y_center;
this.r = radius;
};
Solution.prototype.randPoint = function() {
while (true) {
const x = Math.random() * (2 * this.r) - this.r;
const y = Math.random() * (2 * this.r) - this.r;
if (x * x + y * y <= this.r * this.r) {
return [this.xc + x, this.yc + y];
}
}
};
复杂度分析
- 时间复杂度:期望时间复杂度为 O(1)。
- 空间复杂度:O(1)。