Matlab 如何在不知道何时停止的情况下将随机值重复添加到空向量中?如何计算平均步数?

Matlab 如何在不知道何时停止的情况下将随机值重复添加到空向量中?如何计算平均步数?,matlab,random,montecarlo,Matlab,Random,Montecarlo,想象一下,通过从空向量开始,然后在v的末尾重复随机选择1到20的数字,形成向量v的过程。如何使用Matlab来调查在v包含从1到20的所有数字之前平均需要多少步?您可以在回答中定义/使用任意数量的函数或脚本 v=[]; v=zeros(1,20); for a = 1:length(v) v(a)=randi(20); end 因为v现在只是一个1x20向量,如果有两个数字相等,它肯定是 不是所有的20个数字都在1到20之间 for i = 1:length(v) for j = i

想象一下,通过从空向量开始,然后在
v
的末尾重复随机选择1到20的数字,形成向量
v
的过程。如何使用Matlab来调查在
v
包含从1到20的所有数字之前平均需要多少步?您可以在回答中定义/使用任意数量的函数或脚本

v=[];
v=zeros(1,20);

for a = 1:length(v)
  v(a)=randi(20);
end
因为
v
现在只是一个1x20向量,如果有两个数字相等,它肯定是 不是所有的20个数字都在1到20之间

for i = 1:length(v)
  for j = i+1:length(v)
    if v(i)==v(j) 
      v=[v randi(20)];
      i=i+1;
      break;
    end
  end
end



for k = 1:length(v)
  for n = 1:20
    if v(k)==n
      v=v;
    elseif v(k)~=n
      a=randi(20);
      v=[v a];
    end
    if a~=n
      v=[v randi(20)];
      k=k+1;
      break;
    end
  end
end

disp('number of steps: ')
i*k

我不确定我是否正确理解了您的问题,但也许可以看看
unique()
函数

如果

那么向量中的所有值都是1:20

v = []
counter = 0;
while length(unique(v)) ~= 20
    a = randi(20);
    v=[v a];
    counter = counter +1
end
计数器
应提供在v包含所有值之前所需的迭代次数


如果您想通过试错法获得平均迭代次数,只需查看一下这段代码,并对其进行10000次测试,然后从
计数器中取结果的平均值

首先,生成向量的循环必须是无限的。如果你的条件得到满足,你可以跳出这个循环。这就是你如何计算你需要多少步骤。如果您知道需要更多的步骤,则不能使用超过20个步骤的循环。我喜欢使用
而true
break

接下来,确定是否存在所有元素的方法是O(n2)方法。这可以通过对元素进行O(n logn)排序来完成。这就是
unique
所做的。它通过排序工作,在一般情况下,排序是O(n logn)(想想快速排序)。因此,绘制
n
元素,并在每次检查它们是否都得到之后,都是一个操作O(n2 log n)。这太贵了

但我们这里讨论的是一组有限的整数。整数可以按O(n)排序(查找直方图排序或基数排序)。但我们可以做得更好,因为我们甚至不需要物理地创建向量或对其值进行排序。相反,我们可以简单地跟踪在长度为20的数组中看到的元素:在循环中,生成下一个向量元素,在20个元素的数组中设置相应的值,当该数组的所有元素都被设置时,您至少已经看到了所有值一次。这是你休息的时候

下面是我对这两种方法的实现。
unique
方法需要11秒来重复10000次,而另一种方法只需要0.37秒。在10000次重复之后,我发现平均需要72步才能看到所有20个整数

function test

k = 10000;

tic;
n1 = 0;
for ii=1:k
   n1 = n1 + method1;
end
n1 = n1 / k;
toc
disp(n1)

tic;
n2 = 0;
for ii=1:k
   n2 = n2 + method2;
end
n2 = n2 / k;
toc
disp(n2)

end

function n = method1
k = 20;
v = [];
n = 1;
while true
   v(end+1) = randi(k);
   if numel(unique(v))==k
      break;
   end
   n = n + 1;
end
end

function n = method2
k = 20;
h = zeros(20,1);
n = 1;
while true
   h(randi(k)) = 1;
   if all(h)
      break;
   end
   n = n + 1;
end
end

注意计时:我在这里使用
tic
/
toc
,但通常最好使用
timeit
。时间差足够大,所以这一点无关紧要。但一定要确保使用
tic
/
toc
的代码在函数中,而不是复制粘贴到命令行。在命令行上使用
tic
/
toc
时,计时不具有代表性,因为不会使用JIT编译器。

stats.stackexchange上的以下问题包含一个Matlab模拟,询问您需要滚动六面模具多少次才能至少一次获得1-6之间的所有数字:非常感谢!!!这个很好用!!我希望这就是他们要问的。非常感谢!我只是matlab的初学者。。我还在想把我的“休息”放在哪里……我会学习你的第二种方法!
function test

k = 10000;

tic;
n1 = 0;
for ii=1:k
   n1 = n1 + method1;
end
n1 = n1 / k;
toc
disp(n1)

tic;
n2 = 0;
for ii=1:k
   n2 = n2 + method2;
end
n2 = n2 / k;
toc
disp(n2)

end

function n = method1
k = 20;
v = [];
n = 1;
while true
   v(end+1) = randi(k);
   if numel(unique(v))==k
      break;
   end
   n = n + 1;
end
end

function n = method2
k = 20;
h = zeros(20,1);
n = 1;
while true
   h(randi(k)) = 1;
   if all(h)
      break;
   end
   n = n + 1;
end
end