Permutation transformation: Minimum operations to achieve permutation
Last Updated :
02 Oct, 2023
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++
#include <bits/stdc++.h>
using namespace std;
void checkPermutation( int n, int arr[])
{
set< int > st;
for ( int i = 1; i <= n; i++) {
st.insert(i);
}
vector< int > v;
for ( int i = 0; i < n; i++) {
if (st.find(arr[i]) == st.end()) {
v.push_back(arr[i]);
}
else {
st.erase(arr[i]);
}
}
sort(v.begin(), v.end());
reverse(v.begin(), v.end());
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" ;
}
}
int main()
{
int n = 5;
int arr[n] = { 2, 3, 4, 4, 5 };
checkPermutation(n, arr);
return 0;
}
|
Java
import java.util.*;
public class PermutationCheck {
public static void checkPermutation( int n, int [] arr)
{
Set<Integer> st = new HashSet<>();
for ( int i = 1 ; i <= n; i++) {
st.add(i);
}
List<Integer> v = new ArrayList<>();
for ( int i = 0 ; i < n; i++) {
if (!st.contains(arr[i])) {
v.add(arr[i]);
}
else {
st.remove(arr[i]);
}
}
Collections.sort(v);
Collections.reverse(v);
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());
}
}
public static void main(String[] args)
{
int n = 5 ;
int [] arr = { 2 , 3 , 4 , 4 , 5 };
checkPermutation(n, arr);
}
}
|
Python3
def checkPermutation(n, arr):
st = set ( range ( 1 , n + 1 ))
v = []
for i in range (n):
if arr[i] not in st:
v.append(arr[i])
else :
st.remove(arr[i])
v.sort(reverse = 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))
if __name__ = = "__main__" :
n = 5
arr = [ 2 , 3 , 4 , 4 , 5 ]
checkPermutation(n, arr)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
public class PermutationCheck
{
public static void CheckPermutation( int n, int [] arr)
{
HashSet< int > st = new HashSet< int >();
for ( int i = 1; i <= n; i++)
{
st.Add(i);
}
List< int > v = new List< int >();
for ( int i = 0; i < n; i++)
{
if (!st.Contains(arr[i]))
{
v.Add(arr[i]);
}
else
{
st.Remove(arr[i]);
}
}
v.Sort();
v.Reverse();
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);
}
}
public static void Main( string [] args)
{
int n = 5;
int [] arr = { 2, 3, 4, 4, 5 };
CheckPermutation(n, arr);
}
}
|
Javascript
function checkPermutation(n, arr) {
const st = new Set();
for (let i = 1; i <= n; i++) {
st.add(i);
}
const v = [];
for (let i = 0; i < n; i++) {
if (!st.has(arr[i])) {
v.push(arr[i]);
} else {
st. delete (arr[i]);
}
}
v.sort((a, b) => b - a);
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);
}
}
const n = 5;
const arr = [2, 3, 4, 4, 5];
checkPermutation(n, arr);
|
Time complexity: O(n*logn)
Auxiliary Space: O(n)
Share your thoughts in the comments
Please Login to comment...