Lexicographically smallest permutation with distinct elements using minimum replacements

Given an array of n positive integers such that each element of integer is from 1 to n. Find the lexicographically permutation that can be obtained by replacing minimum number of elements in array such that every element of array occurs exactly one in the entire array. First print the minimum number of replacement required and then print the final lexicographical array.
Examples:

Input arr[] = {2, 3, 4, 3, 2}
Output 2
           1 3 4 5 2
Explanation
Replace number '2' at position 1st with number 
'1' and '3' at position 4th with number '5'. 
The array that we obtain is [1, 3, 4, 5, 2]
which is lexicographically smallest among all 
the possible suitable.

Input arr[] = {2, 1, 2, 1, 2}
Output 3
           2 1 3 4 5 


Naive approach is to generate all the permutation from 1 to n and pick the smallest one which renders the minimum replacements. Time complexity of this approach is O(n!) which will definitely time out for large value of n.

Efficient approach is to pick desired elements greedily. Firstly initialize the cnt[] array which will contains the frequency of elements occuring in the array. For each element of array(ai), occurred more than once in an array, add the numbers in ascending order because of getting lexicographically minimal permutation. For instance,
Iterate the array over all elements. Let the current number of array is ai. If count of ai is equals to 1 then move to next number of array. If count of ai is greater than 1 then replace the number ai with element ele(smallest number which is not occurred in array) only if ele < ai. Meanwhile decrease the count of ai in cnt[] array.
If ele > ai then mark the number ai so that we can replace it in next iteration. This step this need because we need to make smallest lexicographically permutation.

For example, let’s suppose the arr[] = {1, 5, 4, 5, 3, 7, 3}
In first iteration ‘5’ occurs two times in array(indexing 1),
therefore we have to replace ‘5’ at position ‘2’ with ‘2’(2 < 5).
Now the updated array = {1, 2, 4, 5, 3, 7, 3}

In next iteration, ‘3’ would be consider as it occurs two times
in array. But this time the next element of replacement would
be equals to 6 which is greater than 3. Therefore visit element
3 in boolean array vis[] and iterate over other elements.
Now again ‘3’ occurred at position 7th, this time replace it with
number ‘6’.
Final array is arr[] = {1, 2, 4, 5, 3, 7, 6}

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to print lexicographically
// permutation array by replacing minimum
// element of array
#include <bits/stdc++.h>
using namespace std;
  
// Function to calculate lexicographically permutation
// in array
void lexicoSmallestPermuatation(int arr[], int n)
{
    // Calculate frequency of array elements
    int cnt[n + 1];
    memset(cnt, 0, sizeof(cnt));
    for (int i = 0; i < n; ++i)
        ++cnt[arr[i]];
  
    int ele = 1, replacement = 0;
    bool vis[n + 1];
    memset(vis, 0, sizeof(vis));
    for (int i = 0; i < n; ++i) {
  
        // If count of element is 1, no
        // need to replace
        if (cnt[arr[i]] == 1)
            continue;
  
        // Find the element that has not
        // occurred in array
        while (cnt[ele])
            ++ele;
  
        // If replacement element is greater
        // than current arr[i] then visit
        // that element for next iteration
        if (ele > arr[i] && !vis[arr[i]])
            vis[arr[i]] = 1;
  
        else {
  
            // Decrement count and assign the element
            // to array
            --cnt[arr[i]];
            arr[i] = ele;
  
            // Increment the replacement count
            ++replacement;
  
            // Increment element after assigning
            // to the array
            ++ele;
        }
    }
  
    cout << replacement << "\n";
    for (int i = 0; i < n; ++i)
        cout << arr[i] << " ";
}
  
// Driver code
int main()
{
    int arr[] = { 2, 3, 4, 3, 2 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    lexicoSmallestPermuatation(arr, sz);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to print lexicographically
// permutation array by replacing minimum
// element of array
  
class GFG {
  
// Function to calculate lexicographically permutation
// in array
    static void lexicoSmallestPermuatation(int arr[], int n) {
        // Calculate frequency of array elements
        int cnt[] = new int[n + 1];
        for (int i = 0; i < n; ++i) {
            ++cnt[arr[i]];
        }
  
        int ele = 1, replacement = 0;
        boolean vis[] = new boolean[n + 1];
        for (int i = 0; i < n; ++i) {
  
            // If count of element is 1, no
            // need to replace
            if (cnt[arr[i]] == 1) {
                continue;
            }
  
            // Find the element that has not
            // occurred in array
            while (cnt[ele]>0) {
                ++ele;
            }
  
            // If replacement element is greater
            // than current arr[i] then visit
            // that element for next iteration
            if (ele > arr[i] && !vis[arr[i]]) {
                vis[arr[i]] = true;
            } else {
  
                // Decrement count and assign the element
                // to array
                --cnt[arr[i]];
                arr[i] = ele;
  
                // Increment the replacement count
                ++replacement;
  
                // Increment element after assigning
                // to the array
                ++ele;
            }
        }
  
        System.out.print(replacement + "\n");
        for (int i = 0; i < n; ++i) {
            System.out.print(arr[i] + " ");
        }
    }
  
// Driver code
    public static void main(String[] args) {
        int arr[] = {2, 3, 4, 3, 2};
        int sz = arr.length;
        lexicoSmallestPermuatation(arr, sz);
  
    }
  
// This code is contributed by 29AjayKumar

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 program to print lexicographically
# permutation array by replacing minimum
# element of array
  
# Function to calculate lexicographically 
# permutation in array
def lexicoSmallestPermuatation(arr, n):
      
    # Calculate frequency of array elements
    cnt = [0 for i in range(n + 1)]
    for i in range(n):
        cnt[arr[i]] += 1
  
    ele = 1
    replacement = 0
    vis = [0 for i in range(n + 1)]
    for i in range(n):
          
        # If count of element is 1, no
        # need to replace
        if (cnt[arr[i]] == 1):
            continue
  
        # Find the element that has not
        # occurred in array
        while (cnt[ele]):
            ele += 1
  
        # If replacement element is greater
        # than current arr[i] then visit
        # that element for next iteration
        if (ele > arr[i] and vis[arr[i]] == 0):
            vis[arr[i]] = 1;
  
        else:
              
            # Decrement count and assign 
            # the element to array
            cnt[arr[i]] -= 1
            arr[i] = ele
  
            # Increment the replacement count
            replacement += 1
  
            # Increment element after assigning
            # to the array
            ele += 1
      
    print(replacement)
    for i in range(n):
        print(arr[i], end = " ")
  
# Driver code
if __name__ == '__main__':
    arr = [2, 3, 4, 3, 2]
    sz = len(arr)
    lexicoSmallestPermuatation(arr, sz)
      
# This code is contributed by
# Shashank_Sharma

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

      
// C# program to print lexicographically 
// permutation array by replacing minimum 
// element of array  
using System;
public class GFG { 
  
// Function to calculate lexicographically permutation 
// in array 
    static void lexicoSmallestPermuatation(int []arr, int n) { 
        // Calculate frequency of array elements 
        int []cnt= new int[n + 1]; 
        for (int i = 0; i < n; ++i) { 
            ++cnt[arr[i]]; 
        
  
        int ele = 1, replacement = 0; 
        bool []vis = new bool[n + 1]; 
        for (int i = 0; i < n; ++i) { 
  
            // If count of element is 1, no 
            // need to replace 
            if (cnt[arr[i]] == 1) { 
                continue
            
  
            // Find the element that has not 
            // occurred in array 
            while (cnt[ele]>0) { 
                ++ele; 
            
  
            // If replacement element is greater 
            // than current arr[i] then visit 
            // that element for next iteration 
            if (ele > arr[i] && !vis[arr[i]]) { 
                vis[arr[i]] = true
            } else
  
                // Decrement count and assign the element 
                // to array 
                --cnt[arr[i]]; 
                arr[i] = ele; 
  
                // Increment the replacement count 
                ++replacement; 
  
                // Increment element after assigning 
                // to the array 
                ++ele; 
            
        
  
        Console.Write(replacement + "\n"); 
        for (int i = 0; i < n; ++i) { 
            Console.Write(arr[i] + " "); 
        
    
  
// Driver code 
    public static void Main() { 
        int []arr = {2, 3, 4, 3, 2}; 
        int sz = arr.Length; 
        lexicoSmallestPermuatation(arr, sz); 
  
    
  
// This code is contributed by Rajput-Ji//

chevron_right


PHP

$arr[$i] && !$vis[$arr[$i]])
$vis[$arr[$i]] = 1;

else
{

// Decrement count and assign the
// element to array
–$cnt[$arr[$i]];
$arr[$i] = $ele;

// Increment the replacement count
++$replacement;

// Increment element after assigning
// to the array
++$ele;
}
}

echo $replacement. “\n”;
for ($i = 0; $i < $n; ++$i) echo $arr[$i] . " "; } // Driver code $arr = array(2, 3, 4, 3, 2 ); $sz = sizeof($arr); lexicoSmallestPermuatation($arr, $sz); // This code is contributed by ita_c ?>

Output

2
1 3 4 5 2 

Time complexity: O(n)

This article is contributed by Shubham Bansal. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.



My Personal Notes arrow_drop_up