持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
题目
给定圆的半径和圆心的位置,实现函数 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]
提示:
0 < radius <= 10^8-10^7 <= x_center, y_center <= 10^7randPoint最多被调用3 * 10^4次
思考
本题难度中等。
首先是读懂题意。我们要在半径为radius、圆心位置(x_center, y_center)的圆中随机选择一个点。
我们可以使用拒绝采样的方法来解决这个问题。圆的半径为 R,那么我们可以使用一个边长为 2R 的正方形,在正方形内生成均匀随机点,也就是对于横坐标和纵坐标分别生成一个随机数即可。拒绝采样的意思是,如果生成的点落在圆内,我们就返回这个点,否则我们拒绝这个点,重新生成,直到新的随机点落在圆内。
点落在圆中的概率是 πR^2 / 4R^2 ≈ 0.785,因此期望的生成次数 ≈1.274,时间复杂度为 O(1)。
解答
方法一:拒绝采样
/**
* @param {number} radius
* @param {number} x_center
* @param {number} y_center
*/
var Solution = function(radius, x_center, y_center) {
this.xc = x_center
this.yc = y_center
this.r = radius
}
/**
* @return {number[]}
*/
Solution.prototype.randPoint = function() {
while (true) {
// 在 [-R, R) 的范围内生成随机数
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]
}
}
}
// 执行用时:136 ms, 在所有 JavaScript 提交中击败了67.11%的用户
// 内存消耗:57.1 MB, 在所有 JavaScript 提交中击败了69.74%的用户
// 通过测试用例:8 / 8
复杂度分析:
- 时间复杂度:O(1)。
- 空间复杂度:O(1)。