JavaScript(Firefox 30 +),74字节
(n,k,i=0,j=k)=>[for(_ of Array(q=k+n-1))if(Math.random(++i)<k/q--)i-j+k--]
说明
xnor出色的Python答案很好地总结了此处使用的技术如何/为什么起作用。第一步是创建范围[1,2,...,n + k-1]:
(n,k,i=0)=>[for(_ of Array(q=k+n-1))++i]
接下来,我们需要从该范围中提取k个随机项。为此,我们需要选择概率为s / q的每个项目,其中s是仍需要的项目数,q是该范围内剩余的项目数。由于我们使用的是数组推导,因此这很简单:
(n,k,i=0)=>[for(_ of Array(q=k+n-1))if(Math.random(++i)<k/q--)k--&&i]
这给了我们一个均匀分布的递增数字序列。可以通过减去我们先前发现的项j的数量来解决此问题:
(n,k,i=0,j=0)=>[for(_ of Array(q=k+n-1))if(Math.random(++i)<k/q--)k--&&i-j++]
最后,通过将k存储在j中,我们可以将其合并k--
到表达式中并节省一些字节:
(n,k,i=0,j=k)=>[for(_ of Array(q=k+n-1))if(Math.random(++i)<k/q--)i-j+k--]