1

I want to randomly generate a permutation P of the first n natural numbers, and it has to satisfy that P[i] != i for every i<n.

How can I do it efficiently?


The first method I came up with is just to randomly select legal numbers for each position iteratively. However I found it doesn't seem to guarantee the randomness.

For example in the case of 4 numbers, if I (randomly) choose 2,3 for first two numbers, then the configuration for the last two numbers could be either 0,1 or 1,0. If I happen to choose say 1,2 for the first two, then the only available option left is 3,0 since the last bit can't be 3. So it seems the probability of 1,2,3,0 is twice as high as 2,3,0,1, right?

Another thing to do is to randomly generate a permutation and reject if it doesn't satisfy the condition, but the time complexity for this can't be guaranteed.

dontloo
  • 10,067
  • 4
  • 29
  • 50
  • 1
    What you mean is "uniformly distributed". "randomly" does not say the probabilities are equal. – Henry Jun 12 '17 at 06:46
  • @Henry right, I meant "uniformly distributed" indeed – dontloo Jun 12 '17 at 06:49
  • 1
    You could use a [Fisher-Yates Shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) to randomize the initial sequence. In case, one element is wrongly placed, swap it with its neighbour. If more elements are wrongly placed, perform a second Fisher-Yates shuffle of these elements. – Axel Kemper Jun 12 '17 at 06:53
  • For large n the probability that a permutation has no fixed point tends to 1/e. So the strategy to reject permutations with a fixed point will on average need e (2.718...) tries. During the generation of the unrestricted permutation you can also "fail fast" if you detect that there will be a fixed point to speed the process up a bit. So this should not behave too badly in practice. – Henry Jun 12 '17 at 07:27
  • @Henry good to know that, thank you – dontloo Jun 13 '17 at 02:24
  • @JohnColeman thank you that seems exactly my question – dontloo Jun 13 '17 at 02:24

1 Answers1

1

You could do trial-and-error with Fisher-Yates shuffle. The probability of computing a permutation P with fixed points is 1-1/e which means that the expected number of trials is e (or about three).

Here I am using the known fact that if the probability of seeing heads when throwing a biased coin is p then the expected number of trials until getting the first heads is 1/p.

The total expected running time is then O(n).

Also note that is asymptotically optimal as any algorithm that computes a random permutation without fixed points has to touch all of the elements.

Pseudo code:

generateRandomPermutation(n)
    do
        generate a random permutation P of {1,2,3,...,n} with Fisher-Yates // O(n)
    while there exists i with P[i] = i // Expected nr of iterations is e
    return P
blazs
  • 4,705
  • 24
  • 38
  • @JohnColeman ah, I misunderstood the question. I thought that we are given an integer `i` which mustn't be fixed (and that this is the only constraint); in that case my argument works. If the problem is to find a permutation with no fixed points then yes, we expect to make three (actually `e`) iterations. Thanks for the heads-up; I updated the answer. – blazs Jun 12 '17 at 12:00
  • 2
    OP's question wasn't phrased very clearly since they neglected to quantify `i`. Your original interpretation was reasonable enough. As an optimization you can short-circuit Fisher-Yates as soon as you see a fixed point, though in languages that have a built-in shuffle it might not be worth the hassle. – John Coleman Jun 12 '17 at 12:04