• 382. Linked List Random Node


    问题:

    给定一个链表,求随机抽取一个元素。

    使得每个元素被取出的概率相同。

    Example 1:
    Input
    ["Solution", "getRandom", "getRandom", "getRandom", "getRandom", "getRandom"]
    [[[1, 2, 3]], [], [], [], [], []]
    Output
    [null, 1, 3, 2, 2, 3]
    
    Explanation
    Solution solution = new Solution([1, 2, 3]);
    solution.getRandom(); // return 1
    solution.getRandom(); // return 3
    solution.getRandom(); // return 2
    solution.getRandom(); // return 2
    solution.getRandom(); // return 3
    // getRandom() should return either 1, 2, or 3 randomly. Each element should have equal probability of returning.
     
    
    Constraints:
    The number of nodes in the linked list will be in the range [1, 10^4].
    -10^4 <= Node.val <= 10^4
    At most 10^4 calls will be made to getRandom.
    

      

    解法:math,概率,priority_queue

    解法一:math,概率

    从给定的链表中,取出一个数:

    • 那么我们遍历这个链表的所有元素,
    • 进行随机选取:
      • 当遍历到第i个数,若满足一定条件,我们将这个数取出作为结果。
        • 这个条件是:
        • 实现:从[0~i)中取随机数,若该随机数==0,则取出当前数。这个概率== 1/i
      • 不取出这个数作为结果(替换掉之前的结果)的概率==1-1/i

    那么对于某个数 i,我们遍历完所有数,将其取得的概率即为:

    • (我们只可能从遍历到 第 i 个数 开始)
    • 当前取得这个数 i 作为结果,然后遍历其他数时,不再选取其他数来替代当前结果。
      • 1/i * (1-1/(i+1)) * (1-1/(i+2)) *...* (1-1/n)
      • = 1/i * (i/(i+1)) * ((i+1)/(i+2)) *...* ((n-1)/n)
      • = 1/n

    满足题意:概率相同都为1/n

    代码参考:

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode() : val(0), next(nullptr) {}
     7  *     ListNode(int x) : val(x), next(nullptr) {}
     8  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     9  * };
    10  */
    11 class Solution {
    12 public:
    13     ListNode* h;
    14     /** @param head The linked list's head.
    15         Note that the head is guaranteed to be not null, so it contains at least one node. */
    16     Solution(ListNode* head) {
    17         h=head;
    18     }
    19     
    20     /** Returns a random node's value. */
    21     int getRandom() {
    22         ListNode* p = h;
    23         int res=p->val;
    24         int i=0;
    25         //cout<<res<<endl;
    26         while(p) {
    27             i++;
    28             //cout<<","<<i;
    29             int rd = rand() % i;
    30             //cout<<rd<<endl;
    31             if(rd==0) res = p->val;
    32             //chosen probability=1/i;
    33             //not chosen probability=1-1/i;
    34             p=p->next;
    35         }
    36         // the probablity that k is chosen :
    37         // from i==k to i==n, that k can be chosen.
    38         // 1/k * (1-1/(k+1)) * (1-1/(k+2)) *...* (1-1/n)
    39         //=1/k * (k/(k+1)) * ((k+1)/(k+2)) *...* ((n-1)/n)
    40         //=1/n
    41         return res;
    42     }
    43 };
    44 
    45 /**
    46  * Your Solution object will be instantiated and called as such:
    47  * Solution* obj = new Solution(head);
    48  * int param_1 = obj->getRandom();
    49  */

    解法二:priority_queue

    每次抽取一个数时:

    遍历所有的数,对每个数分配随机数,

    并将这个随机数作为权值,加入优先队列,

    遍历完毕后,出队一个元素(权值最大or最小),则为随机选取的数。

    代码参考:

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode() : val(0), next(nullptr) {}
     7  *     ListNode(int x) : val(x), next(nullptr) {}
     8  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     9  * };
    10  */
    11 typedef pair<int, int> pii;
    12 class Solution {
    13 public:
    14     ListNode* h;
    15     /** @param head The linked list's head.
    16         Note that the head is guaranteed to be not null, so it contains at least one node. */
    17     Solution(ListNode* head) {
    18         h=head;
    19     }
    20     
    21     /** Returns a random node's value. */
    22     int getRandom() {
    23         ListNode* p = h;
    24         priority_queue<pii, vector<pii>, greater<pii>> q;
    25         while(p) {
    26             int rd = rand();
    27             q.push({rd, p->val});
    28             p=p->next;
    29         }
    30         return q.top().second;
    31     }
    32 };
    33 
    34 /**
    35  * Your Solution object will be instantiated and called as such:
    36  * Solution* obj = new Solution(head);
    37  * int param_1 = obj->getRandom();
    38  */
  • 相关阅读:
    android模拟器EditText 不能用物理键盘输入,也不能用电脑键盘输入
    Java中HashMap遍历的两种方式
    Android平台下基于XMPP的IM研究
    基于MINA框架快速开发网络应用程序
    Java中ArrayList遍历的4种方法
    Java在ACM中的应用
    Java大数
    zoj 1406 Jungle Roads
    hdoj 1009 FatMouse' Trade
    Action 相关组件
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/14621590.html
Copyright © 2020-2023  润新知