How to shuffle list in O(n) in OCaml?

送分小仙女□ 提交于 2019-12-18 05:56:50

问题


It is not hard to shuffle an array in O(n), with in place swapping,

How to do it for list in OCaml, with O(n)?


Requirement:

  1. No array or in place usage

  2. Consider this as an interview question


回答1:


Lists are immutable, and there's often a log n price to pay for working with immutable data. If you're willing to pay this cost, there's an obvious n log n approach: tag each list element with a random value, sort based on random value, remove random values. This is the way I shuffle lists in my production code.

Here is the shuffle code from the iOS apps that I sell:

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



回答2:


You could mimick the riffle shuffle for cards.

A riffle shuffle of a deck of cards means to:

  • cut the deck in two parts
  • interleave the two parts

It is actually easier to do the reverse permutation:

  • have two auxiliary lists A and B, iter through your original list L and push each element randomly (with probability 1/2) in front of A or B.
  • L := List.rev A @ List.rev B (this can be tail recursive with a custom List.rev).
  • repeat k times.

According to "Mathematical developments from the analysis of riffle shuffling, by Persi Diaconis, 2002", choose k = 3/2 log_2(n) + c. Indeed, the total variation distance between uniformity and the result falls exponentially fast to 0: it is approximately halved each time you increment c. You could choose c=10.

Space O(1) (if you destroy L), time O(n log n). But there are O(n log n) calls to the random generator, while Jeffrey Scofield's solution only needs O(n) random bits, but Θ(n) space.



来源:https://stackoverflow.com/questions/15095541/how-to-shuffle-list-in-on-in-ocaml

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!