假如,给定一个数组,如何等概率返回数组中任意下标的数,很简单。
对于链表或者流式数据,并不能知道其长度,怎么等概率返回其中任意一个节点
思路是这样的:
对于第一个数,我们以1的概率接受它,但最后不一定就是它,因为后面的过程,还是有概率替换掉这个元素。
对于第二个数,以1/2的概率接受它,
对于第三个数,以1/k的概率接受它,
最后一直遍历完所有的数,就可以证明,最后抽样出来的数一定是等概率的。
对于第一个数,其最终被接受的概率是1*(1-1/2)*(1-1/3)*(1-1/N) = 1/N
对于第二个数,也是一样
对于第k个数,前面解不接受都无所谓,主要是看从k到N 1/k *( 1-1/k+1) *(1-1/(k+2)) * (1-1/N)=1/N
class Solution {
public:
/** @param head The linked list's head.
Note that the head is guaranteed to be not null, so it contains at least one node. */
ListNode* head;
Solution(ListNode* head) {
this->head = head;
}
/** Returns a random node's value. */
int getRandom() {
auto p = head;
int i = 1, res;
while(p){
int rate = random()%i++;
if(rate==0) res = p->val;
p=p->next;
}
return res;
}
};