1

Usually a random permutation for an array with n elements means a uniform distribution from n! possibilities, and the Knuth shuffle is used to do so:

for i from n − 1 downto 1 do
  j ← random integer with 0 ≤ j ≤ i
    exchange a[j] and a[i]

But with the constraint that a[i] != i, I have no idea how to form such a permutation uniformly.

For example, with n = 3, how to form a permutation randomly from the possibilities below?

{1, 2, 0}, {2, 0, 1}

peter
  • 1,034
  • 1
  • 9
  • 23

2 Answers2

2

Permutation without fixed points is called derangement

As the number of derangemets is O(n!), just like the number of permutations, generating all permutations and filtering those which are not derangements wouldn't hurt your performance.

Quick search returned me these slides, which describe another algorithm.

Rafał Rawicki
  • 22,324
  • 5
  • 59
  • 79
  • 1
    Thanks, I have also found the formal paper of this algorithm [here](http://www.siam.org/proceedings/analco/2008/anl08_022martinezc.pdf). – peter Mar 08 '12 at 02:36
0

You didn't state how large your arrays are or how concerned you are with efficiency. One possible solution would simply be to do the Knuth shuffle, then test to see if your constraint is satisfied and redo the shuffle if not.

If you want a bit better efficiency, you could try this instead. Because i is decreasing, after the step exchange a[j] and a[i], a[i] is fixed. So simply modify the algorithm to:

for i from n − 1 downto 1 do
  j ← random integer with 0 ≤ j ≤ i; repeat until a[j] != i
    exchange a[j] and a[i]
Chowlett
  • 45,935
  • 20
  • 116
  • 150
  • The complexity does not matter, but I need to prove that it is uniformly distributed. A simple result satisfying the constraint is not enough. – peter Mar 07 '12 at 09:31
  • On the understanding that your random function is, then this is. The original Knuth shuffle was uniformly distributed over all perms - in particular it has equal chance of producing each constrained permutation. Simply throwing away the result if it doesn't match the constraint and trying again won't change that. – Chowlett Mar 07 '12 at 09:35
  • Take a look at this: http://stackoverflow.com/questions/7279895/shuffle-list-ensuring-that-no-item-remains-in-same-position, it seems that this algorithm has been tested to be not uniform. – peter Mar 08 '12 at 02:29
  • That... surprises and intrigues me. I'll have to read up on why. – Chowlett Mar 08 '12 at 16:46
  • Glad to hear that. I'm also interested in the reason, if you can later share it with me. – peter Mar 09 '12 at 01:57
  • @peter - Ah, I think the _second_ algorithm I've shown is non-uniform (which I find easier to believe). I don't think that post argues that the first algorithm (Knuth shuffle then reject) is non-uniform? – Chowlett Mar 09 '12 at 09:09
  • I agree. 'Shuffle then reject' would take exp(1) times on average, but is uniform. The second algorithm does not even work correctly all the time. I'd prefer 'shuffle then reject', though there exists other faster but more complicated algorithms. – peter Mar 10 '12 at 15:48