Smallest Derangement of Sequence

Given the sequence 

\ S = {1, 2, 3 \dots N} \

find the lexicographically smallest (earliest in dictionary order) derangement of 

\ S \

A derangement of S is as any permutation of S such that no two elements in S and its permutation occur at same position.



Examples:  

Input: 3
Output : 2 3 1
Explanation: The Sequence is 1 2 3.
Possible permutations are (1, 2, 3), (1, 3, 2),
          (2, 1, 3), (2, 3, 1), (3, 1, 2) (3, 2, 1).
Derangements are (2, 3, 1), (3, 1, 2).
Smallest Derangement: (2, 3, 1)

Input : 5
Output : 2 1 4 5 3.
Explanation: Out of all the permutations of 
(1, 2, 3, 4, 5), (2, 1, 4, 5, 3) is the first derangement.

Method 1: 
We can modify the method shown in this article: Largest Derangement 
Using a min heap we can successively get the least element and place them in more significant positions, taking care that the property of derangement is maintained. 

Complexity: O(N * log N)

Below is the implementation of the above approach.  

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to generate smallest derangement
// using priority queue.
#include <bits/stdc++.h>
using namespace std;
 
void generate_derangement(int N)
{
    // Generate Sequence and insert into a
    // priority queue.
    int S[N + 1];
    priority_queue<int, vector<int>, greater<int> > PQ;
    for (int i = 1; i <= N; i++) {
        S[i] = i;
        PQ.push(S[i]);
    }
 
    // Generate Least Derangement
    int D[N + 1];
    for (int i = 1; i <= N; i++) {
        int d = PQ.top();
        PQ.pop();
        if (d != S[i] || i == N) {
            D[i] = d;
        }
        else {
            D[i] = PQ.top();
            PQ.pop();
            PQ.push(d);
        }
    }
 
    if (D[N] == S[N])
       swap(D[N-1], D[N]);
 
    // Print Derangement
    for (int i = 1; i <= N; i++)
        printf("%d ", D[i]);   
    printf("\n");
}
 
// Driver code
int main()
{
    generate_derangement(10);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to generate
// smallest derangement
// using priority queue.
import java.util.*;
class GFG{
 
static void generate_derangement(int N)
{
  // Generate Sequence and insert
  // into a priority queue.
  int []S = new int[N + 1];
   
  PriorityQueue<Integer> PQ =
                new PriorityQueue <>();
   
  for (int i = 1; i <= N; i++)
  {
    S[i] = i;
    PQ.add(S[i]);
  }
 
  // Generate Least Derangement
  int []D = new int[N + 1];
   
  for (int i = 1; i <= N; i++)
  {
    int d = PQ.peek();
    PQ.remove();
    if (d != S[i] || i == N)
    {
      D[i] = d;
    }
    else
    {
      D[i] = PQ.peek();
      PQ.remove();
      PQ.add(d);
    }
  }
 
  if (D[N] == S[N])
  {
    int t = D[N - 1];
    D[N - 1] = D[N];
    D[N] = t;
  }
 
  // Print Derangement
  for (int i = 1; i <= N; i++)
    System.out.printf("%d ", D[i]);   
  System.out.printf("\n");
}
 
// Driver code
public static void main(String[] args)
{
  generate_derangement(10);
}
}
 
// This code is contributed by Amit Katiyar

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to generate
// smallest derangement
// using priority queue.
using System;
using System.Collections.Generic;
 
class GFG{
 
static void generate_derangement(int N)
{
   
  // Generate Sequence and insert
  // into a priority queue.
  int []S = new int[N + 1];
   
  List<int> PQ = new List <int>();
   
  for(int i = 1; i <= N; i++)
  {
    S[i] = i;
    PQ.Add(S[i]);
  }
 
  // Generate Least Derangement
  int []D = new int[N + 1];
  PQ.Sort();
  for(int i = 1; i <= N; i++)
  {
    PQ.Sort();
     
    int d = PQ[0];
    PQ.RemoveAt(0);
     
    if (d != S[i] || i == N)
    {
      D[i] = d;
    }
    else
    {
      PQ.Sort();
      D[i] = PQ[0];
      PQ.RemoveAt(0);
      PQ.Add(d);
    }
  }
 
  if (D[N] == S[N])
  {
    int t = D[N - 1];
    D[N - 1] = D[N];
    D[N] = t;
  }
 
  // Print Derangement
  for(int i = 1; i <= N; i++)
    Console.Write(D[i] + " "); 
   
  Console.Write("\n");
}
 
// Driver code
public static void Main(String[] args)
{
  generate_derangement(10);
}
}
 
// This code is contributed by Amit Katiyar

chevron_right


Output: 

2 1 4 3 6 5 8 7 10 9 

Method 2 
Since we are given a very specific sequence i.e 

S_i = i \ \ \forall i <= N

We can calculate the answer even more efficiently.
Divide the original sequence into pairs of two elements, and then swap the elements of each pair. 
If N is odd then the last pair needs to be swapped again. 



Pictorial Representation 

 

Complexity: We perform at most N/2 + 1 swaps, so the complexity is O(N).

Why does this method work 
This method is a very specific application of method 1 and is based on observation. Given the nature of the sequence, at position i we already know the least element that can be put, which is either i+1 or i-1. Since we are already given the least permutation of S it is clear that the derangement must start from 2 and not 1 ie of the form i+1 (i = 1). The next element will be of form i – 1 . The element after this will be i + 1 and then next i – 1. This pattern will continue until the end. 
This operation is most easily understood as the swapping of adjacent elements of pairs of elements of S.
If we can determine the least element in constant time, then the complexity overhead from the heap is eliminated. Hence, from O(N * log N) the complexity reduces to O(N). 

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// Efficient C++ program to find smallest
// derangement.
#include <bits/stdc++.h>
 
void generate_derangement(int N)
{       
    // Generate Sequence S
    int S[N + 1];
    for (int i = 1; i <= N; i++)
        S[i] = i;
 
    // Generate Derangement
    int D[N + 1];
    for (int i = 1; i <= N; i += 2) {
        if (i == N && i%N!=0) {
 
            // Only if i is odd
            // Swap D[N-1] and D[N]
            int temp=D[N]
            D[N] = D[N - 1];
            D[N - 1] = temp;
        }
        else {
            D[i] = i + 1;
            D[i + 1] = i;
        }
    }
 
    // Print Derangement
    for (int i = 1; i <= N; i++)
        printf("%d ", D[i]);   
    printf("\n");
}
 
// Driver Program
int main()
{
    generate_derangement(10);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Efficient Java program to find
// smallest derangement.
class GFG
{
     
static void generate_derangement(int N)
{
    // Generate Sequence S
    int S[] = new int[N + 1];
    for (int i = 1; i <= N; i++)
        S[i] = i;
 
    // Generate Derangement
    int D[] = new int[N + 1];
    for (int i = 1; i <= N; i += 2)
    {
        if (i == N)
        {
 
            // Only if i is odd
            // Swap S[N-1] and S[N]
            D[N] = S[N - 1];
            D[N - 1] = S[N];
        }
        else
        {
            D[i] = i + 1;
            D[i + 1] = i;
        }
    }
 
    // Print Derangement
    for (int i = 1; i <= N; i++)
        System.out.print(D[i] + " ");
    System.out.println();
}
 
// Driver Program
public static void main(String[] args)
{
    generate_derangement(10);
}
}
 
// This code is contributed by Arnab Kundu

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Efficient Python3 program to find
# smallest derangement.
 
def generate_derangement(N):
     
    # Generate Sequence S
    S = [0] * (N + 1)
    for i in range(1, N + 1):
        S[i] = i
 
    # Generate Derangement
    D = [0] * (N + 1)
    for i in range(1, N + 1, 2):
        if i == N:
 
            # Only if i is odd
            # Swap S[N-1] and S[N]
            D[N] = S[N - 1]
            D[N - 1] = S[N]
        else:
            D[i] = i + 1
            D[i + 1] = i
 
    # Print Derangement
    for i in range(1, N + 1):
        print(D[i], end = " ")
    print()
 
# Driver Code
if __name__ == '__main__':
    generate_derangement(10)
     
# This code is contributed by PranchalK

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// Efficient C# program to find
// smallest derangement.
using System;
 
class GFG
{
     
static void generate_derangement(int N)
{
    // Generate Sequence S
    int[] S = new int[N + 1];
    for (int i = 1; i <= N; i++)
        S[i] = i;
 
    // Generate Derangement
    int[] D = new int[N + 1];
    for (int i = 1; i <= N; i += 2)
    {
        if (i == N)
        {
 
            // Only if i is odd
            // Swap S[N-1] and S[N]
            D[N] = S[N - 1];
            D[N - 1] = S[N];
        }
        else
        {
            D[i] = i + 1;
            D[i + 1] = i;
        }
    }
 
    // Print Derangement
    for (int i = 1; i <= N; i++)
        Console.Write(D[i] + " ");
    Console.WriteLine();
}
 
// Driver Program
public static void Main()
{
    generate_derangement(10);
}
}
 
// This code is contributed
// by Akanksha Rai

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php
// Efficient PHP program to find smallest
// derangement.
 
function generate_derangement($N)
{    
    // Generate Sequence S
    $S = array();
    for ($i = 1; $i <= $N; $i++)
        $S[$i] = $i;
 
    // Generate Derangement
    $D = array();
    for ($i = 1; $i <= $N; $i += 2)
    {
        if ($i == $N)
        {
 
            // Only if i is odd
            // Swap S[N-1] and S[N]
            $D[$N] = $S[$N - 1];
            $D[$N - 1] = $S[$N];
        }
        else
        {
            $D[$i] = $i + 1;
            $D[$i + 1] = $i;
        }
    }
 
    // Print Derangement
    for ($i = 1; $i <= $N; $i++)
        echo $D[$i] . " ";
    echo "\n";
}
 
// Driver Program
generate_derangement(10);
 
// This code is contributed
// by Akanksha Rai
?>

chevron_right


Output: 

2 1 4 3 6 5 8 7 10 9 

Note: The auxiliary space can be reduced to O(1) if we perform the swapping operations on S itself.

This article is contributed by Sayan Mahapatra. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksfor geeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Article Tags :
Practice Tags :


4


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.