面试问题:
给定所有单元设置为0的NxN板,将M(M E.g。在10x10板中标记30个单元,然后选择单元的概率为0.3。 我的想法是迭代所有单元格并在每个单元格上计算范围[1-100]中的随机数,如果数字小于或等于30,则将单元格标记为1. 面试官对此解决方案印象不深。有什么好主意吗? (您可以使用任何语言)
答案 0 :(得分:3)
将70个零(NxN - M)和30个(M)放入向量中。 Shuffle the vector。通过k
和i = 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