js03基础

诺诺SEO软件包:集文章伪原创、百度网址URL下拉框采集、指数、权重、收录批量查询功能

  返回  

LeetCode 382. 链表随机节点(蓄水池算法)

2021/8/20 22:50:05 浏览:

在这里插入图片描述
思路:
啥是蓄水池算法:
参考链接:https://www.jianshu.com/p/7a9ea6ece2af

给定一个数据流,数据流长度N很大,且N直到处理完所有数据之前都不可知,请问如何在只遍历一遍数据(O(N))的情况下,能够随机选取出m个不重复的数据。

相当于是一串水流,水池只能装下m滴水,那么装满了以后只能随机去掉一滴再放进新的一滴。

解法:

  • 对于前 m m m个数,直接放进水池
  • 之后的数,假设为第 k k k个,那么有 m k \frac{m}{k} km的概率保留,同时水池中的每个数有 m k ∗ 1 m = 1 k \frac{m}{k}*\frac{1}{m}=\frac{1}{k} kmm1=k1的概率被替换

证明:

  • i i i个数能进入蓄水池的概率=第 i i i个数据进入蓄水池的概率乘以之后都不被替换的概率
  • 对于前 m m m个数,每个数进入蓄水池的概率是 1 1 1
  • 到了第 k ( k > m ) k(k>m) k(k>m)个数,进入蓄水池的概率是 m k \frac{m}{k} km
  • 综合起来,对于数据流长度 n n n,前 m m m个数保留在蓄水池的概率为 1 ∗ m m + 1 ∗ m + 1 m + 2 ∗ m + 2 m + 3 ∗ . . . ∗ n − 1 n = m n 1*\frac{m}{m+1}*\frac{m+1}{m+2}*\frac{m+2}{m+3}*...*\frac{n-1}{n}=\frac{m}{n} 1m+1mm+2m+1m+3m+2...nn1=nm;对于 m + 1 m+1 m+1 n n n的数也是同理,最后得出每个数保留在蓄水池概率为 m n \frac{m}{n} nm,得证

通解:

vector<int>solve(vector<int>a, int n, int m) {
    vector<int>ans;
    for(int i = 0;i < m;i++) {
        ans.push_back(a[i]);
    }
    for(int i = m;i < n;i++) {
        int num = rand() % (i + 1);
        if(num < m) {
            ans[num] = a[i];
        }
    }
    return ans;
}

本题等价于 m = 1 m=1 m=1的情况,可得解法如下

class Solution {
public:
    Solution(ListNode* head) {
        this -> head = head;
    }
    int getRandom() {
        ListNode* cur = this -> head;
        int i = 1;
        int val = 0;
        while(cur) {
            if(rand() % i == 0) val = cur -> val;
            i++;
            cur = cur -> next;
        }
        return val;
    }
private:
    ListNode* head;
};

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号