以相等的概率随机标记NxN板上的M个单元

时间:2014-11-21 05:58:12

标签: algorithm random probability

面试问题:

给定所有单元设置为0的NxN板,将M(M

E.g。在10x10板中标记30个单元,然后选择单元的概率为0.3。

我的想法是迭代所有单元格并在每个单元格上计算范围[1-100]中的随机数,如果数字小于或等于30,则将单元格标记为1.

面试官对此解决方案印象不深。有什么好主意吗? (您可以使用任何语言)

2 个答案:

答案 0 :(得分:3)

将70个零(NxN - M)和30个(M)放入向量中。 Shuffle the vector。通过ki = k / 10为您的示例迭代并将每个索引j = k % 10映射到二维索引(更常见地使用N作为除数)。

<强>附录

在查看@cavu的链接后,我决定尝试一下这个方法。这是Ruby中的一个实现:

require 'set'

# implementation of Floyd's uniform subset algorithm for
# values in the range [0,n).
def generateMfromN(m, n)
  s = Set.new
  ((n-m)...n).each {|j| s.add?(rand(j+1)) || s.add(j)}
  s.to_a
end

#initialize a 10x10 array of zeros
a = Array.new(10)
10.times {|i| a[i] = Array.new(10,0)}

# create an array of 10 random indices between 0 and 99,
# map each index to 2-d indices, and set the corresponing
# element to 1.
generateMfromN(10,100).each {|index| a[index/10][index%10] = 1}

# show the results
a.each {|v| puts v.to_s}

这会产生诸如......

之类的结果
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 0, 1, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

并且对于Floyd的算法似乎只需要O(M)工作,因为在M次迭代中,每个元素总是被添加到集合中。

如果M大于N * N / 2,则用1&#39初始化数组,然后按@btilly的建议随机放置零位。

答案 1 :(得分:1)

这可以在预期的运行时间O(m)中完成。

首先让我们讨论一下我们最需要一半董事会的情况。所以m <= n*n/2。对于这种情况,我们可以继续选择随机点并改变它们的值,扔掉,我们之前选择,直到我们有m个。丢弃下一个随机选择的概率绝不会超过一半,因此所需的随机选择数最差2 m = O(m)

如果我们需要超过一半的电路板,则需要时间O(m)将每个单元格翻转为1,然后我们使用前面的解决方案来查找n*n - m个单元格以返回0