478. Generate Random Point in a Circle
1. 问题
给定一个圆的半径和圆心坐标,生成圆内点的坐标。
2. 思路
简单说
(1)在圆内随机取点不好做,但是如果画出这个圆的外接正方形,在正方形里面采样就好做了。
(2)取两个random确定正方形内的横坐标和纵坐标即可在正方形内采样。
(3)如果采样到的点不在圆内,则丢弃,继续采样,当采样的点在圆内,则返回该点。
(4)这样采样可以视作在圆内采样的一种近似,到这里就可以把问题解决了。下面是一些扩展知识。
拒绝采样(Reject Sampling)的解释
这个方法利用了拒绝采样的方法,该方法的详细阐述我在前一篇文章470. Implement Rand10() Using Rand7() (拒绝采样Reject Sampling)中提过,下面的解释以这里面拒绝采样的介绍为基础,沿用里面的符号和式子。
把圆内点的分布当作p(x),圆内可以看作有 \(\pi r^2\)个点,每个点的概率为 $ 1 / (\pi r^2) $。
然后把正方形内点的分布当作q(x),正方形内可以看作有 \(4r^2\)个点,每个点的概率为 $1 / (4r^2) $。
这里我们M取\(4/\pi\)。
我们在\(q(x)\)上采点,每个点采到的概率为$1 / (4r^2) $,乘上M就是 \(1 / (\pi r^2)\),对于每个随机变量,\(M * q(x)\)为\(1 / (\pi r^2)\)。\(p(x)\)是圆内点的分布,当采到的点在圆内时,\(p(x) = 1 / (\pi r^2)\),那么接受概率为\(p(x) / (M * q(x))\)就是1。当采到的点在圆外时,\(p(x)\)为0,所以接受概率为0。
时间复杂度:平均为O(1),最坏情况O(无穷)。
空间复杂度:O(1)。
random调用次数的期望值:2.55
这个期望值的计算参见470. Implement Rand10() Using Rand7() (拒绝采样Reject Sampling),使用错位相减,等比数列的求和以及极限,最后求出是\(2 * \frac{4}{\pi} = 2.55\)。
(方法二)直接在圆上取点
(1)一个半径为R的圆,可以看成无数个半径为r(r<R)的圆组成,我们只需要随机取一个半径,然后随机取一个角度,利用半径和角度即可随机取到我们要的点。
(2)对于角度,随机从\([0, 2\pi]\)取就可以了。点的横坐标和纵坐标需要根据这个角度的sin和cos来得到。
(3)对于半径而言,很容易误以为从\([0,1]\)取个数然后乘以R就可以了,但是我们知道,从半径为r的圆内取点,和从半径为\(R\)的圆内取点,比例是\((r/R)^2\)而不是\(r/R\)。比如说我们在半径为\(R\)的圆内取到半径为\((1/2)R\)的圆内点的概率应该\(1/4\)而不是\(1/2\)。所以应该\([0,1]\)取个数,开个根号之后再乘以R,这样保证了在圆内的等比例采样。
时间复杂度:O(1)
空间复杂度:O(1)
3. 代码
拒绝采样
class Solution(object):
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]
"""
while True:
x = (self.x_center - self.radius) + random.random() * self.radius * 2
y = (self.y_center - self.radius) + random.random() * self.radius * 2
if (x - self.x_center) ** 2 + (y - self.y_center) ** 2 <= self.radius ** 2:
return [x, y]
直接在圆上取点
import random
import math
class Solution(object):
def __init__(self, radius, x_center, y_center):
self.radius = radius
self.x_center = x_center
self.y_center = y_center
def randPoint(self):
r = math.sqrt(random.random()) * self.radius
theta = random.uniform(0, 2*math.pi)
x = self.x_center + r*math.cos(theta)
y = self.y_center + r*math.sin(theta)
return [x, y]
4. 类似题目
470. Implement Rand10() Using Rand7() (拒绝采样Reject Sampling)
519. Random Flip Matrix
478. Generate Random Point in a Circle的更多相关文章
- 【LeetCode】478. Generate Random Point in a Circle 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/generate ...
- [LeetCode] Generate Random Point in a Circle 生成圆中的随机点
Given the radius and x-y positions of the center of a circle, write a function randPoint which gener ...
- [Swift]LeetCode478. 在圆内随机生成点 | Generate Random Point in a Circle
Given the radius and x-y positions of the center of a circle, write a function randPoint which gener ...
- Java – Generate random integers in a rangejava获取某个范围内的一个随机数
In this article, we will show you three ways to generate random integers in a range. java.util.Rando ...
- #227 Generate Random Whole Numbers within a Range
我们之前生成的随机数是在0到某个数之间,现在我们要生成的随机数是在两个指定的数之间. 我们需要定义一个最小值和一个最大值. 下面是我们将要使用的方法,仔细看看并尝试理解这行代码到底在干嘛: Math. ...
- Gym 100956 A Random Points on the Circle
二分答案. 对于每次二分后的答案来说, 先倍增序列,通过 two point 来找到 以每个点为起点的最优的符合答案的在哪里. 然后可以DFS树去判断他的前k祖先之间的距离是不是大于k. 常数有点大. ...
- 519. Random Flip Matrix(Fisher-Yates洗牌算法)
1. 问题 给定一个全零矩阵的行和列,实现flip函数随机把一个0变成1并返回索引,实现rest函数将所有数归零. 2. 思路 拒绝采样 (1)先计算矩阵的元素个数(行乘以列),记作n,那么[0, n ...
- 470. Implement Rand10() Using Rand7() (拒绝采样Reject Sampling)
1. 问题 已提供一个Rand7()的API可以随机生成1到7的数字,使用Rand7实现Rand10,Rand10可以随机生成1到10的数字. 2. 思路 简单说: (1)通过(Rand N - 1) ...
- 【LeetCode】随机化算法 random(共6题)
[384]Shuffle an Array(2019年3月12日) Shuffle a set of numbers without duplicates. 实现一个类,里面有两个 api,struc ...
随机推荐
- m2014-architecture-imgserver->配置lighttpd mod_mem_cache 模块做静态资源服务器
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://freehat.blog.51cto.com/1239536/989171 一 l ...
- M0 M4之UART初始化
新唐的M0/M4 UART都有16级或者64级FIFO,用来缓存UART数据的收/发.例如:如果RX FIFO中断触发级别设为14,UART接收14个字节才会发生RDA(接收数据可得)中断.这样可以降 ...
- JavaScript基础细讲
JavaScript基础细讲 JavaScript语言的前身叫作Livescript.自从Sun公司推出著名的Java语言之后,Netscape公司引进了Sun公司有关Java的程序概念,将自己原 ...
- 广义表操作 (ava实现)——广义表深度、广义表长度、打印广义表信息
广义表是对线性表的扩展——线性表存储的所有的数据都是原子的(一个数或者不可分割的结构),且所有的数据类型相同.而广义表是允许线性表容纳自身结构的数据结构. 广义表定义: 广义表是由n个元素组成的序列: ...
- bigpipe&bigrender
bigpipe: 先输出页面的整体布局,在按块输出输出页面的每个部分.这样可以让服务器的运算.网络的传输和浏览器的渲染并行.适用于服务器运算较慢的时候. bigrender: 主要在浏览器端,先将字符 ...
- vux版本升级
一开始用的笨办法, 先卸载npm uninstall vux --save; 然后在安装npm install vux --save; 卸载的还是蛮快的,安装是在下班的时候,让电脑待机2个小时,第二 ...
- go练习5--生成md5
import "crypto/md5" import "encoding/hex" //go 生成 md5 func T4_1() { m := md5.New ...
- 【MySQL案例】error.log的Warning:If a crash happens thisconfiguration does not guarantee that the relay lo(转)
标签: 1.1.1. If a crash happens thisconfiguration does not guarantee that the relay log info will be c ...
- 微信小程序 --- page.json文件
page.json 文件用于配置当前目录.page.json文件里的配置可以修改 app.json 配置里面的 window:不能覆盖app.json文件里面的 tabBar / 网络超时/ debu ...
- xp系统报错 windows explorer has encountered a problem and needs to close.We are sorry for the inconvenience
xp系统遇到问题: 打开某个软件提示报错信息, windows explorer has encountered a problem and needs to close.We are sorry f ...