持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情
前言
今天的题目为中等,题目的难点在于,对于求平均值的概念会陷入一个误区,就是使用语言提供的随机数就能够求得,但是在对于特殊的情况的时候是不够的,随机的方向可能还需要思考一下。
每日一题
今天的题目是 478. 在圆内随机生成点,难度为中等
-
给定圆的半径和圆心的位置,实现函数 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 <= 108
- -107 <= x_center, y_center <= 107
- randPoint 最多被调用 3 * 104 次
题解
题目的一个重点在于,我们不能够只是简单地通过随机 x 坐标和 y 坐标来获得一个随机的点,因为这样子是不够随机的,假如说你先随机到了一个 x 坐标,那么 y 坐标的范围就会根据于 x 离圆心的距离而发生改变,这样子就不够随机了,并且在多次模拟之后,就会发现中间的点会比两边的稀疏,因为当 x 确定之后,离圆心越远,y 能够随机的返回就变小了,在最极限的切边位置上,只要 x 随机到了切面,那么 y 就已经被固定了,不存在随机一说。
所以我们就要从别的角度出发,要让选出来的这个点足够随机。
面积 和 角度
一旦一个圆的半径确定下来之后,那么这个圆的面积就也可以确定了,我们就可以随机的取一个面积,根据随机的面积来确定这个点到圆心的距离,然后在随机一个角度,就能够确定这个点,这里通过随机半径是不行的,因为半径随机的话是均匀分布的,但是我们的圆从内到外是不均匀的,次数一样的话会导致内部的随机次数更多,外面越少。
这张图就很明显的说明了,不同半径位置的圆,取多个角度,越考中间的圆就会越密集,并不是随机的。
所以我们需要使用面积来做判断而不是直接随机半径。
class Solution {
x: number;
y: number;
area: number;
constructor(radius: number, x_center: number, y_center: number) {
this.x = x_center;
this.y = y_center;
this.area = Math.PI * radius * radius;
}
randPoint(): number[] {
const radian = (Math.random() * 360 * Math.PI) / 180;
const r = Math.sqrt((Math.random() * this.area) / Math.PI);
return [this.x + Math.cos(radian) * r, this.y + Math.sin(radian) * r];
}
}
/**
* Your Solution object will be instantiated and called as such:
* var obj = new Solution(radius, x_center, y_center)
* var param_1 = obj.randPoint()
*/