LeetCode:382. Linked List Random Node(蓄水池抽樣算法C++)

382. Linked List Random Node


Given a singly linked list, return a random node’s value from the linked list. Each node must have the same probability of being chosen.

Follow up:
What if the linked list is extremely large and its length is unknown to you? Could you solve this efficiently without using extra space?

Example:

// Init a singly linked list [1,2,3].
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
Solution solution = new Solution(head);

// getRandom() should return either 1, 2, or 3 randomly. Each element should have equal probability of returning.
solution.getRandom();


1、傳說中的蓄水池抽樣算法(此處水池大小爲1),共有N個元素,等概推導:假定第m個選中的概率爲1/m,則結果爲1/m*(1-1/(m+1))…….(1-1/(N-1))(1-1/N)=1/m(m/(1+m))……((N-2)/(N-1))*((N-1)/N)=1/N。可見他的出現是所有數字中等概出現的。至於爲什麼不算前面的,因爲我現在已經處理到了第m個,保存到了該值,只有後面的結果對他有影響。
2、隨機數產生:

uniform_int_distribution<unsigned> u(0,i);
default_random_engine e(rand());
unsigned int m=u(e);

第一條語句是分佈類型,閉區間[a,b];第二條語句是引擎;第三條映射(將分佈類型映射到指定引擎)。注意到給引擎的種子,是爲了不讓序列重複。本來可以用time(0),但發現循環不管用,後來用rand()發現不會,百度得知他會在動調用srand()。另外,對於static,他可以讓隨機數接二連三產生,而不是重複的從一個地方產生。但在這裏環境不能用,在vs裏面嘗試發現也不行,每次都會選中末尾元素,暫時還沒有找出原因。
3、蓄水池抽樣算法(水池大小爲K):此時我們需要先給水池填滿前K值,然後再由後續的值進行替換。思路都是一樣的,推導由前面的1換成K就好了。


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
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. */
    Solution(ListNode* head):cur(head) {
    }

    /** Returns a random node's value. */
    int getRandom() {
        int val=cur->val;
        ListNode *temp=cur;
        for(int i=0;temp!=nullptr;temp=temp->next,++i)
        {
            uniform_int_distribution<unsigned> u(0,i);
            default_random_engine e(rand());//真正隨機的種子
            unsigned int m=u(e);
            if(m<1)
            {
                val=temp->val;
            }
        }
        return val;
    }
private:
    ListNode *cur;
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution obj = new Solution(head);
 * int param_1 = obj.getRandom();
 */

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章