How to randomize order of approximately 20 elements with lowest complexity? (generating random permutations)
-
What do you mean by cca? – Stefan Kendall Nov 07 '09 at 01:48
-
Canonical correlation analysis? – Murali VP Nov 07 '09 at 01:49
-
more about this http://www.freebase.com/view/en/circa – Ante Nov 07 '09 at 01:58
-
*ca.* and *cca.* are both abbreviations for *circa*, although *circa* is only used to refer to dates: http://en.wikipedia.org/wiki/Circa – ThisSuitIsBlackNot Nov 07 '09 at 02:00
-
1Isn't this a duplicate of a list shuffle question? http://stackoverflow.com/questions/375351/most-efficient-way-to-randomly-sort-shuffle-a-list-of-integers-in-c – Mathias Nov 07 '09 at 02:28
4 Answers
Knuth's shuffle algorithm is a good choice.

- 11,918
- 5
- 42
- 52
-
1Well I am disappointed that that is the answer. Since you have to first iterate through the list to fill it and then shuffle it (with an admittedly good algorithm), I would have thought that there was a better solution. – SourceOverflow Oct 30 '17 at 11:37
Some months ago I blogged about obtaining a random permutation of a list of integers. You could use that as a permutation of indexes of the set containing your elements, and then you have what you want.
In the first post I explore some possibilities, and finally I obtain "a function to randomly permutate a generic list with O(n) complexity", properly encapsulated to work on immutable data (ie, it is side-effect free).
In the second post, I make it uniformely distributed.
The code is in F#, I hope you don't mind!
Good luck.
EDIT: I don't have a formal proof, but intuition tells me that the complexity of such an algorithm cannot be lower than O(n). I'd really appreciate seeing it done faster!

- 37,201
- 11
- 119
- 156
-
1All permutations must be possible, and re-arranging an array into a derangement (that is, a permutation `p` for which `p(k) != k` for all `k`) requires that every element be visited. Hence O(n) worst case. Or is that still not formal enough? – Steve Jessop Nov 07 '09 at 03:25
-
Also O(n) average case by the same proof, come to think of it, since IIRC the proportion of permutations of (1...n) which are derangements approaches 1/e as n approaches infinity. – Steve Jessop Nov 07 '09 at 03:27
A simple way to randomise the order is to make a new list of the correct size (20 in your case), iterate over the first list, and add each element in a random position to the second list. If the random position is already filled, put it in the next free position.
I think this pseudocode is correct:
list newList
foreach (element in firstList)
int position = Random.Int(0, firstList.Length - 1)
while (newList[position] != null)
position = (position + 1) % firstList.Length
newList[position] = element
EDIT: so it turns out that this answer isn't actually that good. It is neither particularly fast, nor particularly random. Thankyou for your comments. For a good answer, please scroll back to the top of the page :-)

- 24,300
- 14
- 68
- 71
-
In the worst case this algorithm is O(n^2) (ie, if your random number generator says "1, 1, 1, 1, 1, 1, 1, ...", I let you calculate the rest), not very optimized. – Bruno Reis Nov 07 '09 at 02:23
-
2Putting items in the next free position makes it less random. The items will keep their original order more than in a truly random shuffle. To fix that you would have to pick a new random position when a position is taken, which of course makes it a lot slower. – Guffa Nov 07 '09 at 03:00
-
That's a good point Guffa. I'd never realised that. Thanks. At least I've learnt something here :-) – David Johnstone Nov 07 '09 at 03:19
Probably someone already implemented the shuffling for you. For example, in Python you can use random.shuffle
, in C++ random_shuffle
, and in PHP shuffle
.

- 31,943
- 5
- 40
- 57
-
Surprisingly, in PHP it is called `shuffle` :) I'll update my answer. – Roberto Bonvallet Nov 07 '09 at 14:08