在圆内随机生成点

124 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第39天,点击查看活动详情

478. 在圆内随机生成点 - 力扣(Leetcode)

给定圆的半径和圆心的位置,实现函数 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^7
  • randPoint 最多被调用 3 * 10^4 次

思路

看到题目首先想到的是随机一个半径值r(0 <= r <= radius),随机一个角度deg(0 <= deg < 360),然后根据rdeg求出一个随机点,但仔细分析,这样随机出来的点是不能均匀分布的,越靠近圆心,点分布的概率越大。我们假设有r1r2r3,且r1 > r2 > r3r1 - r2 == r2 - r3,由于r随机生成,r落到[r1,r2)[r2,r3)之间概率是相等,落到[r1,r2)[r2,r3)环中的点是一样多的,显然[r1,r2)环面积更大,点分布的更稀疏。

我们可以在一个边长为2*radius的正方形中随机生成点,然后判断点是否可以落到半径为radius的圆中,如果点距正方形中心距离小于等于radius,就返回这个点,否则继续随机点,代码如下。

解题

/**
 * @param {number} radius
 * @param {number} x_center
 * @param {number} y_center
 */
var Solution = function (radius, x_center, y_center) {
  this.r = radius;
  this.x = x_center;
  this.y = y_center;
};

/**
 * @return {number[]}
 */
Solution.prototype.randPoint = function () {
  const R = this.r * this.r;
  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 <= R) {
      return [this.x + x, this.y + y];
    }
  }
};

/**
 * Your Solution object will be instantiated and called as such:
 * var obj = new Solution(radius, x_center, y_center)
 * var param_1 = obj.randPoint()
 */

module.exports = Solution;