从小范围中生成随机且不重复的整数

6
我想实现的目标是:
我希望创建一个整数向量,其范围相对较小,并确保没有任何整数后面跟着相同的整数。
例如,这是一个“合法”的向量: [1 3 4 2 5 3 2 3 5 4]
而这是一个“非法”的向量(因为5后面跟着另外一个5): [1 3 4 2 5 5 2 3 5 4]
我已经尝试过randi以及与randperm各种变化的实验,但当我试图生成大约100个元素的向量时,就会被卡住,而这些元素都来自一个很小的范围(即1到5之间的整数)。
该函数运行时间太长了。
以下是我尝试之一:
function result = nonRepeatingRand(top, count)

    result = randi(top, 1, count);

    while any(diff(result) == 0)
         result = randi(top, 1, count);    
    end

end

任何帮助都将不胜感激。谢谢!

3
仅仅是一个小评论。不重复的条件意味着你的向量比较“随机”一些。 - bla
5个回答

12

您要查找的序列可以通过从1生成差异top-1,然后从随机初始值开始计算累积余数top来定义:

function result = nonRepeatingRand(top, count)

    diff = randi(top - 1, 1, count);
    result = rem(cumsum(diff) + randi(1, 1, count) - 1, top) + 1;

end

在我的电脑上,这个程序生成了一个从1到5之间的不重复序列,包含一千万个数字,在0.58秒内完成。


我真的想不出你是怎么想出那个的...?不管怎样,我给你点赞! - Stewie Griffin
1
我突然想到,海报想要实现的约束最容易用差分表达。为什么不先生成差分再从中得到序列呢? - A. Donda
@karl71,我进行了广泛的测试,使用许多非常长的生成序列,从未出现过任何重复。也许您以不同的方式使用“重复数字”?如问题所述,这是关于立即重复的问题,即2 3 2 1 2没有“重复”,但2 3 1 2 2有一个“重复”。 - A. Donda
@karl71,不用担心。 :-) - A. Donda
顺便提一句,如果您需要“完全不重复”,请查看randperm - A. Donda
显示剩余4条评论

2

您可以使用以下代码生成从1到M的不重复随机数:

randperm(M);

如果需要生成K个不重复的从1到M的随机数,可以使用以下代码:

randperm(M, K);

祝您使用愉快!


1
谢谢,但是:你可能已经注意到,这个问题(非常优雅地)在一年前得到了回答,并且正确的答案已经被标记。其次,我担心你没有回答我提出的问题 - 如果我需要一个范围在1-4之间的100个不重复随机整数序列,randperm(4,100)当然会返回错误。 - R. Itzi
你的答案非常简单,但是你是最好的亲爱的,干杯 - Christina

1
不要每次都重新生成序列,而是修复重复的部分。例如:
function result = nonRepeatingRand(top, count)

    result = randi(top, 1, count);

    ind = (diff(result) == 0);
    while any(ind)
        result(ind) = [];
        result(end + 1 : count) = randi(top, 1, count - numel(result));

        ind = (diff(result) == 0);
    end

end

在我的机器上,这将在1.6秒内生成一个由1:5中的1000万个不重复数字组成的序列。

1
我认为我的另一个答案更好:更快,更优雅。 - A. Donda

1

借鉴A. Donda的想法,但改进了实现方法:

r=[randi(top,1,1),randi(top - 1, 1, count-1)];
d=rem(cumsum(r)-1,top)+1;
r的第一个元素是随机选择的起始元素。随后的r元素随机选择与前一个元素的差,使用模算术运算。

0

这样怎么样?

top = 5;
count = 100;
n1 = nan;
out = [];
for t = 1: count 
    n2 = randi(top);
    while n1 == n2
        n2 = randi(top);
    end
    out = [out, n2];
    n1 = n2;
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接