[LeetCode] 478. 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.html

Note:git

  1. input and output values are in floating-point.
  2. radius and x-y position of the center of the circle is passed into the class constructor.
  3. a point on the circumference of the circle is considered to be in the circle.
  4. 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/

https://leetcode.com/problems/generate-random-point-in-a-circle/discuss/154405/C%2B%2B-solution-polar-coordinates

https://leetcode.com/problems/generate-random-point-in-a-circle/discuss/169518/C%2B%2B-AC-solution-using-rejection-sampling

https://leetcode.com/problems/generate-random-point-in-a-circle/discuss/155650/Explanation-with-Graphs-why-using-Math.sqrt()

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索