n个热门物品中,随机选择k个物品
Posted xiaoranone
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了n个热门物品中,随机选择k个物品相关的知识,希望对你有一定的参考价值。
背景:
在推荐系统中,都会维护一个热门的物品的list,可能会有很多人在这个list进行添加。有时我们需要从这个list中随机选择k个热门物品返回给用户,现在如何设计一个函数解决这个问题。
我们要注意两个问题,
- list是增加的,对于增加的数据结构,可以选择一个链表作为基础结构,而不能选择数组。
- 要保证每个物品别选择的概率是相同的,即每一个物品选择的概率都是k / n.(n是长度)
首先定义链表的数据结构
struct listNode
int index; // the index of item
struct listNode * next;
;
目前先给出一个简单的C++代码,马上添加证明,是否满足每一个别选择的概率相同。
/**
* Author: xiaoran
* Time: 2018-09-19 16:50
*
*/
#include <bits\\stdc++.h>
using namespace std;
struct listNode
int index;// the index of item
struct ListNode * next;
;
int getlength(listNode * head)
if(head == NULL) return 0;
int length = 0;
listNode * p = head;
while(p)
length ++;
p = p->next;
return length;
listNode * getKnode(listNode * head, int k)
listNode * p = head;
int cnt = 0;
while(p && cnt < k)
p = p->next;
cnt ++;
return p;
/**
* 1. 因为list是长度的增加的,首先计算list长度
* 2. 每次选择产生一个下标,选择这个下标的对应的值
* 3. 如果当前随机产生的值,不在选则的集合中,则进行插入
* 4. 直到集合大小是k个
*/
void selectKitemsOne(listNode * head, int k, vector<int> &candidate)
if(! head) return;
int n = getlength(head);
if(k > n) return;
// 使用set,记录每次选择的下标
set<int> tmp;
while(tmp.size() < k)
int i = rand() % n;
if(tmp.find(i) == tmp.end()) // 不在集合中进行插入
tmp.insert(i); // 这里不能直接插入第i个元素的index,因为我们用的list,不能直接取到第i个值
// 得到candidate
for(auto it = tmp.begin(); it != tmp.end(); it ++)
candidate.push_back(getKnode(*it));
/**
* 1. 初始化前k个作为候选集
* 2. 从i = k-->n进行遍历,
* 3. 随机产生j = rand() % (i+1), if (j < k) candidate[j] = 第i个的index
*/
void selectKitemsTwo(listNode * head, int k, vector<int> &candidate)
if(! head) return;
int i = 0;
listNode * p = head;
while(p && i < k)
candidate.push_back(p->index);
i ++;
while(p)
int j = rand() % (i+1);
if(j < k)
candidate[j] = p->index;
p = p->next;
i ++;
int main()
return 0;
证明:稍后
以上是关于n个热门物品中,随机选择k个物品的主要内容,如果未能解决你的问题,请参考以下文章