问题描述:
给定一个链表。并不知道这个链表的长度
从头结点走到尾,随机选出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 };