对于无限长数组:
1.随机抽取一个元素
第i个元素被抽取的概率是 1 i \frac{1}{i} i1
2.随机抽取k个元素
第i个元素被抽取更新的概率是:
k
i
\frac{k}{i}
ik
第i个元素被抽取更新到特定位置的概率是:
k
i
1
k
=
1
i
\frac{k}{i}\frac{1}{k}=\frac{1}{i}
ikk1=i1
第i个元素没有被抽取更新到某个特定位置的概率是:
1
−
k
i
1
k
=
1
−
1
i
1-\frac{k}{i}\frac{1}{k}=1-\frac{1}{i}
1−ikk1=1−i1
3.题目
leetcode-398. 随机数索引
思路:使用index记录target是第几次出现的,然后取随机数模index,如果是0,选中
class Solution {
public:
vector<int> nums;
Solution(vector<int>& nums):nums{nums.begin(),nums.end()} {
}
int pick(int target) {
int res=-1;
int index=0;
for(int i=0;i<nums.size();i++){
if(nums[i]==target){
index++;
if(rand()%index==0) res=i;
}
}
return res;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(nums);
* int param_1 = obj->pick(target);
*/
leetcode-382. 链表随机节点
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. */
ListNode* head;
Solution(ListNode* head) :head{head}{
}
/** Returns a random node's value. */
int getRandom() {
ListNode* t=head;
int res;
int i=1;
while(t){
if(rand()%i==0) res=t->val;
t=t->next;
i++;
}
return res;
}
};
随机抽取一个数组中的k个数
[0,k-1]的数先选上,然后[k,end())的数按概率替换[0,k-1]的数
#include<iostream>
#include<vector>
#include<random>
using namespace std;
int main(){
int k=3;
vector<int> nums{1,2,2,3,4,43,534,56,4575,67,58,1};
vector<int> res(k,0);
for(int i=0;i<k;i++)
res[i]=nums[i];
for(int i=k;i<nums.size();i++){
int t=rand()%(i+1);
if(t<k){
res[t]=nums[i];
}
}
for(int i=0;i<res.size();i++){
cout<<res[i]<<endl;
}
return 0;
}