我刚刚在互联网上阅读了一些采访问题,让我对解决方案感到好奇。
问题是这样的。
给定一个数字列表和一个rand(0,1)函数,它返回一个0到1之间的随机整数。提供一个算法,根据rand()函数的输出随机排序给定列表,应该为列表中的每个号码调用一次。
似乎要求生成一个只有0和1的随机数用于随机播放。 我提出了这个解决方案。
int random(int array_index, int array size)
{
return (array_index * 41 * (array_size + rand(0,1)) % array_size;
}
但我觉得这不够好,因为它取决于array_index。
任何人都有更好的答案吗?
答案 0 :(得分:2)
你应该使用Fisher-Yates Shuffle algorithm,它在O(n)时间内执行真正随机的随机播放(即:“为列表中的每个数字调用一次”)。
To shuffle an array a of n elements (indices 0..n-1):
for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]
答案 1 :(得分:1)
假设我有一个10元素列表。然后有10个! = 3628800不同的订购方式。
如果我只能调用rand(0,1)10次,我只能生成2 ^ 10 = 1024个不同的二进制序列。
没有办法唯一地识别10个中的一个!数字在0到1024之间的排序。 那就是我们不能进行无偏见的洗牌。 (除了超过3个元素的列表)。因此,我们现在可以专注于选择易于实施的偏差改组。
例如:
result = new List<int>();
foreach( int i in list )
{
int r = rand(0,1);
if( r == 0 )
result.Prepend(i);
else
result.Append(i);
}
return result;
这非常偏向于将列表中的元素放在远离列表中间的列表中。
答案 2 :(得分:0)
我会用Ruby编写我的,因为我更多地使用它。
def random_sort(numbers)
sorted = Array.new
index = 0
numbers.each do |number|
while rand(1)
index += 1
end
index = index % numbers.length
while numbers[index] != nil
if index > numbers.length - 1
index = 0
continue
end
index += 1
end
sorted[index] = number
end
return sorted
end
答案 3 :(得分:0)
让数组大小为N
要随机播放数字列表,我们使用以下策略。
For the first element we find a position out of the all available N choices.
Then, the second element has N-1 choices and so on.
We generate the N! possible outcomes which ensures all are equi-probable.
现在要从(比如N)选择中随机生成位置,我们执行以下操作; (我们对N-1,N-2 ......也这样做)
Use Divide - And - Conquer.
First modify N to (Least Power of 2 >= N) Example: For N=5, modified_N=8
Run rand(0,1) -
If 0 - we the position is from 1 to modified_N/2
Else - the position is in modified_N/2+1 to modified_N
We do this recursively till we find the final position.
If the final position is between N+1 and modified_N we run this procedure again.
这样我们可以使用rand(0,1)
随机找到一个位置