有一天,需要做一个推送功能,每天在固定的几个时间段向用户推荐电影。
产品提出:每次要随机给用户推送,但不能重复,不能推送当天已经推荐过的电影。
该怎么实现呢?
在需求评审会上,产品一说完,开发同学们立刻炸锅了:“这工作量太大了”,“要存储的信息太多,这么多用户,要保存每个用户推送过的列表”。
确实,我听到这些讨论,下意识也觉得要保存每个用户的推送列表。一方面,用户量太大,存这些数据不现实,成本太高;另一方面,产品的需求也合理,给用户推送当天已经推荐过的电影确实不合适。
存储成本太高,那有没有不需要存储的方案?
既然要求随机但序列可预测、可复现,这其实就是伪随机。
答案一下子就清晰了。只要用每个用户和日期作为固定的随机种子,生成的随机数就是确定的。这样可以用随机数把推荐列表打乱,然后按批次推送。
这是一种高效且均匀的随机洗牌算法,时间复杂度为 O(n)。具体实现步骤如下:
val 初始化随机数生成器。i(从最后一个元素到第二个),生成一个随机索引 j(范围是 [0, i])。arr[i] 和 arr[j]。val 和输入数组,总是得到相同的排序结果。val 会产生完全不同的排序(比如 val=42 和 val=100 的输出完全独立)。举个例子
假设你在洗扑克牌,手里有 10 张牌排成一列:
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10]注:golang中rand.Shuffle就是用的该算法,直接调用就可以了(注意使用固定种子)。完美~

其实记录用户状态不一定非要存下来,有时候利用一些数学特性也能很好地达成期望。另外,虽然我们开发时常常排斥伪随机(比如每次都用当前纳秒作为随机种子),但其实伪随机有时候也挺有用的。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。