Given the radius and x-y positions of the center of a circle, write a function randPoint
which generates a uniform random point in the circle.html
Note:git
randPoint
returns a size 2 array containing x-position and y-position of the random point, in that order.Example 1:github
Input:
["Solution","randPoint","randPoint","randPoint"]
[[1,0,0],[],[],[]] Output: [null,[-0.72939,-0.65505],[-0.78502,-0.28626],[-0.83119,-0.19803]]
Example 2:web
Input:
["Solution","randPoint","randPoint","randPoint"]
[[10,5,-7.5],[],[],[]] Output: [null,[11.52438,-8.33273],[2.46992,-16.21705],[11.13430,-12.42337]]
Explanation of Input Syntax:app
The input is two lists: the subroutines called and their arguments. Solution
's constructor has three arguments, the radius, x-position of the center, and y-position of the center of the circle. randPoint
has no arguments. Arguments are always wrapped with a list, even if there aren't any.dom
这道题给了咱们一个圆,包括中点位置和半径,让随机生成圆中的任意一个点。这里说明了圆上也看成是圆中,并且这里的随机意味着要等几率。思绪飘回了高中时代,努力搜索着那一丝丝残留的记忆,终于,博主把还给老师的知识又要了回来,圆的方程表示为 (x - a) ^ 2 + (y - b) ^ 2 = r ^ 2,这里的 (a, b) 是圆心位置,r为半径。那么如何生成圆中的任意位置呢,若是用这种方式来生成,先随机出一个x,随机出y的时候还要考虑其是否在圆中间,比较麻烦。继续回到高中时代,模糊的记忆中飘来了三个字,极坐标。是的,圆还能够用极坐标的形式来表示,只需随机出一个角度 theta,再随机出一个小于半径的长度,这样就能够获得圆中的坐标位置了,哦耶~ 先来生成 theta吧,因为一圈是 360 度,即 2pi,因此随机出一个 [0, 1] 中的小数,再乘以 2pi,就能够了。而后就是随机小于半径的长度,这里有个问题须要注意一下,这里并非直接随机出一个 [0, 1] 中的小数再乘以半径r,而是要对随机出的 [0, 1] 中的小数取个平方根再乘以半径r。这是为啥呢,简单来讲,是为了保证等几率。若是不用平方根的话,那么表示圆的时候 (len * cos(theta)) ^ 2 + (len * sin(theta) ^ 2,这里就至关于对随机出的 [0, 1] 中的小数平方了,那么其就不是等几率的了,由于两个小于1的小数相乘了,其会更加靠近0,这就是为啥要平方一下的缘由。最后在求点位置的时候要加上圆心的偏移便可,参见代码以下:ide
解法一:post
class Solution { public: Solution(double radius, double x_center, double y_center) { r = radius; centerX = x_center; centerY = y_center; } vector<double> randPoint() { double theta = 2 * M_PI * ((double)rand() / RAND_MAX); double len = sqrt((double)rand() / RAND_MAX) * r; return {centerX + len * cos(theta), centerY + len * sin(theta)}; } private: double r, centerX, centerY; };
咱们也能够不用极坐标来作,因为以前刚作过 Implement Rand10() Using Rand7(),对其中的拒绝采样 Rejection Sampling 还有印象,因此也能够用其来作。这其实就是拒绝采样的经典应用,在一个正方形中有均匀分布的点,随机出其内切圆中的一个点,那么就是随机出x和y以后,而后算其平方和,若是小于等于r平方,说明其在圆内,能够返回其坐标,记得加上圆心偏移,不然从新进行采样。关于拒绝采样的方法能够参见博主以前那篇博客 Implement Rand10() Using Rand7(),参见代码以下:spa
解法二:code
class Solution { public: Solution(double radius, double x_center, double y_center) { r = radius; centerX = x_center; centerY = y_center; } vector<double> randPoint() { while (true) { double x = (2 * (double)rand() / RAND_MAX - 1.0) * r; double y = (2 * (double)rand() / RAND_MAX - 1.0) * r; if (x * x + y * y <= r * r) return {centerX + x, centerY + y}; } } private: double r, centerX, centerY; };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/478
相似题目:
Implement Rand10() Using Rand7()
参考资料:
https://leetcode.com/problems/generate-random-point-in-a-circle/