382. Linked List Random Node - 水池抽样

问题描述:

给定一个链表。并不知道这个链表的长度

从头结点走到尾,随机选出K个结点(只能走一次)

解法:

先把前k个结点放进vector,当遍历到第count个结点时,该结点以k/count的概率进入到vecor中,如果进入vector则随机替换掉vector中已有的一个结点。

证明:

第index个结点进入vector的概率为

不会被第after(after > index)个结点替换掉的概率为(1 - (k/after)*(1/k))= 1 - 1/after = P[after]

所以,第index个结点进入vector中并始终不会被替换的概率为 :(k/index)* P[index+1] * P[index+2] * P[index+3] * ...... * P[n] = k/n

所以对于每个元素都是等概率留在vector中的

 1 class Solution {
 2 public:
 3     /** @param head The linked list's head.
 4         Note that the head is guaranteed to be not null, so it contains at least one node. */
 5     ListNode* head = NULL;
 6     Solution(ListNode* h) {
 7         head = h;
 8     }
 9     
10     vector<ListNode*> getRandomK(int k){
11         ListNode* cur = head;
12         vector<ListNode*> ans;
13         for (int i = 0; i < k && cur != NULL; i++, cur = cur->next) {
14             ans.push_back(cur);
15         }
16         for (int i = k; cur != NULL; i++, cur = cur->next) {
17             int select = rand() % (i + 1);
18             if(select < k){
19                 ans[select] = cur;
20             }
21         } 
22         return ans;
23     }
24     
25     /** Returns a random node's value. */
26     int getRandom() {
27         vector<ListNode*> vec = getRandomK(1);
28         return vec[0]->val;
29     }
30 };

猜你喜欢

转载自www.cnblogs.com/liqiniuniu/p/10863005.html