# 478. Generate Random Point in a Circle

**<font color=red>难度: Medium</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/generate-random-point-in-a-circle/

> 内容描述

```
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.

Note:

input and output values are in floating-point.
radius and x-y position of the center of the circle is passed into the class constructor.
a point on the circumference of the circle is considered to be in the circle.
randPoint returns a size 2 array containing x-position and y-position of the random point, in that order.
Example 1:

Input: 
["Solution","randPoint","randPoint","randPoint"]
[[1,0,0],[],[],[]]
Output: [null,[-0.72939,-0.65505],[-0.78502,-0.28626],[-0.83119,-0.19803]]
Example 2:

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:

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.
```

## 解题方案

> 思路 1
******- 时间复杂度: O(1)******- 空间复杂度: O(1)******



我们先画出这个圆的外接正方形，然后考虑等概率生成这个一个点使得这个点在外接正方形中，如果这个点同时又在圆中，我们就直接返回这个点，
否则重新生成一点继续判断，也称为rejection sampling

```python
class Solution:

    def __init__(self, radius, x_center, y_center):
        """
        :type radius: float
        :type x_center: float
        :type y_center: float
        """
        self.radius = radius
        self.x_center = x_center
        self.y_center = y_center
        

    def randPoint(self):
        """
        :rtype: List[float]
        """
        x = random.uniform(self.x_center-self.radius, self.x_center+self.radius)
        y = random.uniform(self.y_center-self.radius, self.y_center+self.radius)
        if (x - self.x_center) ** 2 + (y - self.y_center) ** 2 <= self.radius ** 2:
            return [x, y]
        return self.randPoint()
```



> 思路 2
******- 时间复杂度: O(1)******- 空间复杂度: O(1)******



也可以考虑用极坐标做，我们知道固定一个点与圆心的距离D之后，其距离圆心越近，出现的概率越大（且是线性的，因为圆的周长和半径成正比），
所以我们不能等概率生成这个距离D。


定义一下pi为距离圆心距离小于等于i的所有点出现的面积，容易发现pi是随着i的线性增长而成平方增长的，因为想让pi呈现为线性增长的话，我们的i必须为sqrt增长

也就是越外面的点出现的概率越小，然后我们极坐标的theta角度可以均匀的从[0, 2*PI]中取得


```python
class Solution:

    def __init__(self, radius, x_center, y_center):
        """
        :type radius: float
        :type x_center: float
        :type y_center: float
        """
        self.radius = radius
        self.x_center = x_center
        self.y_center = y_center
        

    def randPoint(self):
        """
        :rtype: List[float]
        """
        d = self.radius * math.sqrt(random.random())
        theta = random.random() * 2 * math.pi
        return [d * math.cos(theta) + self.x_center, d * math.sin(theta) + self.y_center]
```































