JAVA学习-蓄水池抽样算法

生活中无时不刻都在发生着随机事件,我们并不能改变它的随机性,但是我们可以尝试利用它的概率去做更多有意义的事情。比如有一个高 10 米的蓄水池,我们需要对随机一个 1 米的水层进行抽样,这时候很多人都会想到直接生成一个 (0, 10] 的随机数就可以解决,那么要是把高 10 米的条件去掉呢?这显然就不是一个随机数就能解决的了,这时候就得轮到今天的主角——蓄水池抽样算法登场了。

蓄水池抽样算法是一种不用知道蓄水池深度就可以达到抽样效果的算法,他的核心在于按每一层循序依次进行抽样,不同层的抽样计算如下:

  • 如果池子 1 米,那么第一层一定被选中,概率为 1
  • 如果池子 2 米,那么第二层被选中的概率为 1 / 2,第一层被选中的概率就是第二层不被选中的概率乘上上一层被选中的概率 ,就为 (1 - 1 / 2) * 1 = 1 / 2
  • 如果池子 3 米,那么第三层被选中的概率为 1 / 3,第一层或第二层被选中的概率就是第三层不被选中的概率乘上上一层被选中的概率 ,就为 (1 - 1 / 3) * 1 / 2 = 1 / 3
  • ......
  • 如果池子 n 米,那么第 n 层被选中的概率为 1 / n,其他某一层被选中的概率就为 (1 - 1 / n) * 1 / (n - 1) = 1 / n

这样一看,是不是就保证了每一层被选中的概率是一样的了,每次遍历只需要判断遍历的那一层是否被选中,当遍历结束的时候就可以知道随机的那一层是哪层了。

同样的,利用蓄水池抽样的思想我们也可以解决很多不知道长度或深度的题,比如随机遍历一个文件的一行,随机遍历一个链表的节点,随机点餐等等。

记住,实践是检测真理的唯一标准,大家可以试试去做这一道题:

链表随机节点icon-default.png?t=LBL2https://leetcode-cn.com/problems/linked-list-random-node 

你可能感兴趣的:(Java学习,java,算法,开发语言)