今天leetcode的每日一题382. 链表随机节点的题解中出现了这个算法,因为是第一次了解到这个算法,简单记录一下。
蓄水池抽样算法
从一批总数未知的样本中选取若干个样本,要求每个样本被选取的概率相同。
假设总共有 n 个样本,对每一次抽取,从前往后遍历样本,对遇到的每一个样本做以下事情:
假设当前为第 i 个样本,那么以 的概率将这个样本作为结果样本,的概率保留原来的结果样本
当遍历完整个样本群后,返回结果样本,完成一次抽取
为什么这样能保证每个样本被选取的概率相同呢?
P(第 i 个样本最后被抽取的概率)
= P(遍历到第 i 个样本时被作为结果样本的概率)P(遍历到第 i + 1 个样本时不被作为结果样本的概率)...P(遍历到第 n 个样本时不被作为结果样本的概率)
=
=
=
class Solution {
Random random;
ListNode head;
public Solution(ListNode x) {
random = new Random();
head = x;
}
public int getRandom() {
int i = 0;
int ans = 0;
ListNode t = head;
//每一次抽取都需要遍历整个样本
while(t != null && ++i > 0 ){
// 等于 0 的概率为 1/i
if(random.nextInt(i) == 0){
ans = t.val;
}
t = t.next;
}
return ans;
}
}