How to generate permutations where a[i] != i?

后端 未结 6 534
野的像风
野的像风 2021-01-18 12:11

Suppose I have an array of integers int a[] = {0, 1, ... N-1}, where N is the size of a. Now I need to generate all permutations of

6条回答
  •  滥情空心
    2021-01-18 12:59

    The permutations you are looking for are called derangements. As others have observed, uniformly randomly distributed derangements can be generated by generating uniformly randomly distributed permutations and then rejecting permutations that have fixed points (where a[i] == i). The rejection method runs in time e*n + o(n) where e is Euler's constant 2.71828... . An alternative algorithm similar to @Per's runs in time 2*n + O(log^2 n). However, the fastest algorithm I've been able to find, an early rejection algorithm, runs in time (e-1)*(n-1). Instead of waiting for the permutation to be generated and then rejecting it (or not), the permutation is tested for fixed points while it is being constructed, allowing for rejection at the earliest possible moment. Here's my implementation of the early rejection method for derangements in Java.

      public static int[] randomDerangement(int n)
        throws IllegalArgumentException {
    
        if (n<2)
          throw new IllegalArgumentException("argument must be >= 2 but was " + n);
    
        int[] result = new int[n];
        boolean found = false;
    
        while (!found) {
          for (int i=0; i=0; i--) {
            int j = rand.nextInt(i+1);
            if (i == result[j]) {
              fixed = true;
              break;
            }
            else {
              int temp = result[i];
              result[i] = result[j];
              result[j] = temp;
            }
         }
          if (!fixed) found = true;
        }
    
        return result;
      }
    

    For an alternative approach, see my post at Shuffle list, ensuring that no item remains in same position.

提交回复
热议问题