在O(n)中使用array
进行随机交换并不难,
如何在OCaml中为list
执行此操作,使用O(n)?
要求:
没有数组或就地使用
将此视为面试问题
答案 0 :(得分:10)
列表是不可变的,并且通常需要支付 log n 的价格来处理不可变数据。如果您愿意支付此费用,则会有明显的 n log n 方法:使用随机值标记每个列表元素,根据随机值排序,删除随机值。这是我在生产代码中随机播放列表的方式。
以下是我销售的iOS应用中的随机播放代码:
let shuffle d =
let nd = List.map (fun c -> (Random.bits (), c)) d in
let sond = List.sort compare nd in
List.map snd sond
答案 1 :(得分:0)
你可以模仿卡片的浅滩洗牌。
一副纸牌的轻微洗牌意味着:
反向排列实际上更容易:
根据“浅滩改组分析的数学发展,由Persi Diaconis,2002”,选择k = 3/2 log_2(n)+ c。实际上,均匀性和结果之间的总变化距离以指数方式快速下降到0:每次增加c时它大约减半。你可以选择c = 10。
空间O(1)(如果你摧毁L),时间O(n log n)。但是对随机生成器有O(n log n)次调用,而Jeffrey Scofield的解决方案只需要O(n)个随机位,但是Θ(n)空间。