我有一个数组,说:books[10]
,
以及一个链表,例如:bookList
。
我想将books[10]
中的所有元素插入到链接列表中,但是以随机顺序插入。
解决方案1: 对阵列进行随机播放,然后从0插入到长度为1。
解决方案2: 按原样从0插入到长度为1,然后随机播放链接列表。
解决方案3:
生成indexArray= {0, 1, 2, ..., length-1}
的Fisher-Yates混洗数组,然后按顺序将元素插入到链表中:
for(i = 0; i < indexArray.length; i ++)
bookList.add(books[indexArray[i]]);
目前我使用1似乎是最简单的,我认为解决方案3会更好,如果我的数组中的对象很大,因为我不必将原始数组洗牌而是一个int数组对于索引而言。
有更好的解决方案吗?
答案 0 :(得分:0)
另一种解决方案是将方法(1)和(3)结合起来:
(有关参考,请参阅http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle的“现代算法”部分。)
i
的索引n
重置为1
(使用基于1的索引)。m
和1
之间选择一个随机数i
。m
处的数组元素插入到链接列表的前面。 (我们将从前到后构建列表,但实际上如果您决定在列表后面插入条目则没有任何区别。从后到前构建可以避免跟踪指向后面的指针列表,以避免在每一步扫描到最后导致O(n)
插入时间。)i
处的数组元素移动到索引为m
的插槽。这避免了就地shuffle的少量开销,避免了生成索引数组的内存开销,并避免了与方法(2)相关联的链表的复杂的就地混乱。它在O(n)
时间运行,使用O(1)
额外内存(忽略用于原始数组和链表的内存)。
编辑:我认为上面描述的算法实际上应该是最容易实现的三个选项。除非您的阵列非常大,否则您所拥有的选项的实际运行时和内存使用差异可能会微不足道。
如果数组中条目的大小确实很大,则此算法会遇到与就地shuffle相同的问题,即必须移动大数据集,并且在这种情况下可能生成一个列表指数更好。