(1)概念
蓄水池抽样算法(Reservoir Sampling)是一种用于从 大规模数据集(尤其是 流式数据 或 无法预先知晓数据总量 的场景)中 等概率随机抽取固定数量样本 的算法。
(2)实现
我们怎么实现蓄水池抽样算法
我们假设在1到total个数据中 等概率的抽取samp个数 存放到数组arry中
我们对于
我们可以这样处理
- 初始化:蓄水池大小为 samp,先将前 samp 个元素放入蓄水池。
-
遍历后续每个元素:第 i 个元素,(i > samp)对于第 i 个元素,以
的概率决定是否将其放入蓄水池。
- 若放入,则在蓄水池中随机选择一个元素(共 samp个位置,每个位置被替换的概率为
进行替换
(1)对于前samp个数
遍历完依然存在于蓄水池的概率==从第samp+1个数开始到samp+2,samp+3……total没有被替换的概率==
(2)对于第samp+1个数到total个数
第samp+i个数 i=1,2,3......total-samp
被放到数组的概率为 |
最后依然存在数组的概率==被放到数组的概率*第samp+i,samp+i+1,samp+i+2……total个数都没有被替换掉的概率==
这样我们就可以实现只用遍历一遍就可以实现每个元素被选到的概率是相同的
概率都是
最后代码奉上
class Solution
{
public:
//代码功能在1到total中随机取samp个数 并且每个数取到的概率相同
vector<int> solution(int total, int samp)
{
s.clear();
for (int i = 1;i <= samp;i++)
{
s.push_back(i);
}
srand((unsigned int)time(NULL));
for (int j = samp + 1;j <= total;j++)
{
randomNumber = rand() % j;
if (randomNumber < samp)
{
s[randomNumber] = j;
}
}
return s;
}
private:
vector<int> s;
int randomNumber = 0;
};
class Solution
{
public:
//代码功能在1到total中随机取samp个数 并且每个数取到的概率相同
vector<int> solution(int total, int samp)
{
s.clear();
for (int i = 1;i <= samp;i++)
{
s.push_back(i);
}
srand((unsigned int)time(NULL));
for (int j = samp + 1;j <= total;j++)
{
randomNumber = rand() % j;
if (randomNumber < samp)
{
s[randomNumber] = j;
}
}
return s;
}
private:
vector<int> s;
int randomNumber = 0;
};