Open In App

Permutation transformation: Minimum operations to achieve permutation

Last Updated : 02 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of length n, the task is to find the minimum number of operations required to make a permutation of integers 1 to n where you are allowed to select any element arr[i] and replace it with arr[i] % x (x is any positive integer). If it is not possible to make a permutation return -1.

Examples:

Input: n = 5, arr[] = {2, 3, 4, 4, 5}
Output: 1
Explanation: One way to make the given array a permutation of integers 1 to 5 is to perform the following operations:

  • Select arr3 = 4 and replace it with arr3 % 3 = 1.

After these operations, the array becomes [2, 3, 4, 1, 5], which is a permutation of integers 1 to 5. Therefore, the minimum number of operations required is 1.

Approach: This can be solved with the following idea:

To make the given array a permutation of integers 1 to n, we need to ensure that all the elements in the range 1 to n are present exactly once in the array arr. We can achieve this by performing the operation on the elements in the array that are either greater than n or repeated. By performing the operation on any element arri, we can convert it to any positive number less than floor((arri-1)/2). Since the maximum value of ai% x for any arbitrary x can be floor ((arri-1)/2), we can use this fact to ensure that all the elements in the range 1 to n are present exactly once in the array arr.

Below are the steps involved:

  • First creates a set containing integers from 1 to n and a vector to store elements that are not part of the permutation.
  • It then iterates over the input array and removes the elements from the set if they are present, and adds them to the vector otherwise.
  • The vector is then sorted in descending order.
  • It then iterates over the elements in the vector, and for each element, it finds the largest integer s in the set and each integer in the vector say z such that (z-1)/2 < s.  The reason for this condition is that whenever we apply operation z%x where x is any positive integer the result will be always less than (z-1)/2. If such an integer exists, it removes it from the set. If not, it sets a flag and exits the loop.
  • Finally, it outputs the size of the vector if the flag is not set, or -1 otherwise.

Below is the implementation of the above approach:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
void checkPermutation(int n, int arr[])
{
 
    // Set to store elements from 1 to n
    set<int> st;
    for (int i = 1; i <= n; i++) {
        st.insert(i);
    }
 
    // vector stores all the elements
    // which are not present in set or
    // repeated finally set stores the
    // element missing from the array
    // in range 1 to n.
    vector<int> v;
 
    for (int i = 0; i < n; i++) {
 
        // Element is not present
        // in the set.
        if (st.find(arr[i]) == st.end()) {
 
            v.push_back(arr[i]);
        }
 
        else {
            st.erase(arr[i]);
        }
    }
 
    // Sorting element in decending order
    // in vector v
    sort(v.begin(), v.end());
    reverse(v.begin(), v.end());
 
    // If it is impossible to convert
    // array in permutation of 1 to n
    // flag will be true
    bool flag = false;
    for (auto z : v) {
        auto it = st.end();
        it--;
        int s = *it;
        if ((z - 1) / 2 < s) {
            flag = true;
            break;
        }
        st.erase(it);
    }
    if (flag) {
        cout << "-1"
             << "\n";
    }
    else {
        cout << v.size() << "\n";
    }
}
 
// Driver code
int main()
{
    int n = 5;
    int arr[n] = { 2, 3, 4, 4, 5 };
 
    // Function call
    checkPermutation(n, arr);
    return 0;
}


Java




// Java program to illustrate Minimum operation to achieve
// permutation
import java.util.*;
 
public class PermutationCheck {
 
    public static void checkPermutation(int n, int[] arr)
    {
        // Set to store elements from 1 to n
        Set<Integer> st = new HashSet<>();
        for (int i = 1; i <= n; i++) {
            st.add(i);
        }
 
        // ArrayList stores all the elements
        // which are not present in the set or
        // repeated. Finally, set stores the
        // element missing from the array
        // in the range 1 to n.
        List<Integer> v = new ArrayList<>();
 
        for (int i = 0; i < n; i++) {
            // Element is not present in the set.
            if (!st.contains(arr[i])) {
                v.add(arr[i]);
            }
            else {
                st.remove(arr[i]);
            }
        }
 
        // Sorting elements in descending order in the
        // ArrayList v
        Collections.sort(v);
        Collections.reverse(v);
 
        // If it is impossible to convert the array into a
        // permutation of 1 to n, flag will be true
        boolean flag = false;
        for (int z : v) {
            Iterator<Integer> it = st.iterator();
            int s = 0;
            while (it.hasNext()) {
                s = it.next();
            }
            if ((z - 1) / 2 < s) {
                flag = true;
                break;
            }
            st.remove(s);
        }
        if (flag) {
            System.out.println("-1");
        }
        else {
            System.out.println(v.size());
        }
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int n = 5;
        int[] arr = { 2, 3, 4, 4, 5 };
 
        // Function call
        checkPermutation(n, arr);
    }
}
 
// This code is contributed by shivamgupta0987654321


Python3




# Python code for the above approach
def checkPermutation(n, arr):
    # Set to store elements from 1 to n
    st = set(range(1, n + 1))
 
    # List stores all the elements which are not present in set or repeated
    # Finally, set stores the element missing from the array in the range 1 to n.
    v = []
 
    for i in range(n):
        # Element is not present in the set.
        if arr[i] not in st:
            v.append(arr[i])
        else:
            st.remove(arr[i])
 
    # Sorting element in descending order in list v
    v.sort(reverse=True)
 
    # If it is impossible to convert the array into a permutation of 1 to n, flag will be true
    flag = False
    for z in v:
        s = max(st)
        if (z - 1) // 2 < s:
            flag = True
            break
        st.remove(s)
 
    if flag:
        print("-1")
    else:
        print(len(v))
 
# Driver code
if __name__ == "__main__":
    n = 5
    arr = [2, 3, 4, 4, 5]
 
    # Function call
    checkPermutation(n, arr)
 
# This code is contributed by Susobhan Akhuli


C#




// C# program to illustrate Minimum operation to achieve
// permutation
using System;
using System.Collections.Generic;
using System.Linq;
 
public class PermutationCheck
{
    public static void CheckPermutation(int n, int[] arr)
    {
        // Set to store elements from 1 to n
        HashSet<int> st = new HashSet<int>();
        for (int i = 1; i <= n; i++)
        {
            st.Add(i);
        }
 
        // List stores all the elements
        // which are not present in the set or
        // repeated. Finally, set stores the
        // element missing from the array
        // in the range 1 to n.
        List<int> v = new List<int>();
 
        for (int i = 0; i < n; i++)
        {
            // Element is not present in the set.
            if (!st.Contains(arr[i]))
            {
                v.Add(arr[i]);
            }
            else
            {
                st.Remove(arr[i]);
            }
        }
 
        // Sorting elements in descending order in the
        // List v
        v.Sort();
        v.Reverse();
 
        // If it is impossible to convert the array into a
        // permutation of 1 to n, flag will be true
        bool flag = false;
        foreach (int z in v)
        {
            IEnumerator<int> it = st.GetEnumerator();
            int s = 0;
            while (it.MoveNext())
            {
                s = it.Current;
            }
            if ((z - 1) / 2 < s)
            {
                flag = true;
                break;
            }
            st.Remove(s);
        }
        if (flag)
        {
            Console.WriteLine("-1");
        }
        else
        {
            Console.WriteLine(v.Count);
        }
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int n = 5;
        int[] arr = { 2, 3, 4, 4, 5 };
 
        // Function call
        CheckPermutation(n, arr);
    }
}
 
// This code is contributed by Pushpesh Raj


Javascript




// JavaScript code for the above approach
 
function checkPermutation(n, arr) {
    // Set to store elements from 1 to n
    const st = new Set();
    for (let i = 1; i <= n; i++) {
        st.add(i);
    }
 
    // Array to store all the elements
    // which are not present in the set or repeated
    // Finally, the set stores the element missing from the array in the range 1 to n.
    const v = [];
 
    for (let i = 0; i < n; i++) {
        // Element is not present in the set.
        if (!st.has(arr[i])) {
            v.push(arr[i]);
        } else {
            st.delete(arr[i]);
        }
    }
 
    // Sorting elements in descending order in the array v
    v.sort((a, b) => b - a);
 
    // If it is impossible to convert the array into a permutation of 1 to n, flag will be true
    let flag = false;
    for (const z of v) {
        const s = Math.max(...st);
        if ((z - 1) / 2 < s) {
            flag = true;
            break;
        }
        st.delete(s);
    }
    if (flag) {
        console.log("-1");
    } else {
       console.log(v.length);
    }
}
 
// Driver code
const n = 5;
const arr = [2, 3, 4, 4, 5];
 
// Function call
checkPermutation(n, arr);
 
// This code is contributed by Susobhan Akhuli


Output

1



Time complexity: O(n*logn)
Auxiliary Space: O(n)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads