Given an array arr[] of size N, the task is to find the minimum number of operations to convert the array into a permutation of [1, n], in each operation, an element a[i] can be replaced by a[i] % d where d can be different in each operation performed. If it is not possible print -1.
Examples:
Input: arr[] = {5, 4, 10, 8, 1}
Output: 2
Explanation: In first operation choosing d = 7 , 10 can be replaced by 10 % 7 ,
In second operation d = 6, 8 can be replaced by 8 %6 so two operations.
Input : arr[] = {1, 2, 3, 7}
Output: -1
Approach: The task can be solved using the greedy approach. This approach is based on the fact that when remainder r is to be obtained, then a[i] > 2*r i.e r lies between the range [0, a[i]-1 /2]
Let us take an example: 8 for different d
Taking, 8 % 7= 1
8%6 = 2
8%5 = 3
8%4 = 0
8%3 = 2
8%2 = 0
8%1=0
So maximum number that can be obtained is 3 using mod operation, so when we want to obtain a number i in a permutation then the number should a[i] > 2* i+1
Follow these steps to solve this problem:
- Initialize a set s
- Traverse through the array arr[] & insert all the elements of arr[] into the set.
- Initialize a variable ops = 0
- Now iterate from n to 1
- Check if s has i already if it has removed it from the set.
- Else increment ops and check if the largest element of the set < 2* i +1
- If the largest of the set is < 2* i +1 then set ops = -1 and break out of the loop.
- Else erase it from the set because we can make it i using mod operation.
- Print the ops
`Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void minimum_operations( int arr[], int n)
{
set< int > s;
for ( int i = 0; i < n; i++) {
s.insert(arr[i]);
}
int ops = 0;
for ( int i = n; i >= 1; i--) {
if (s.find(i) != s.end()) {
s.erase(s.find(i));
}
else {
ops++;
auto it = s.end();
it--;
if (*it < 2 * i + 1) {
ops = -1;
break ;
}
s.erase(it);
}
}
cout << ops << endl;
}
int main()
{
int arr[] = { 5, 4, 10, 8, 1 };
int n = sizeof (arr) / sizeof (arr[0]);
minimum_operations(arr, n);
return 0;
}
|
Java
import java.util.*;
class GFG{
static void minimum_operations( int arr[], int n)
{
SortedSet<Integer> s = new TreeSet<Integer>();
for ( int i = 0 ; i < n; i++) {
s.add(arr[i]);
}
int ops = 0 ;
for ( int i = n; i >= 1 ; i--) {
if (s.contains(i)) {
s.remove(i);
}
else {
ops++;
Integer it = s.last();
it--;
if (it < 2 * i + 1 ) {
ops = - 1 ;
break ;
}
s.remove(it);
}
}
System.out.print(ops + "\n" );
}
public static void main(String[] args)
{
int arr[] = { 5 , 4 , 10 , 8 , 1 };
int n = arr.length;
minimum_operations(arr, n);
}
}
|
Python3
def minimum_operations(arr, n):
s = set ([])
for i in range (n):
s.add(arr[i])
ops = 0
for i in range (n, 0 , - 1 ):
if (i in s):
list (s).remove(i)
else :
ops + = 1
it = len (s)
it - = 1
if ( list (s)[it] < 2 * i + 1 ):
ops = - 1
break
list (s).pop(it)
print (ops)
if __name__ = = "__main__" :
arr = [ 5 , 4 , 10 , 8 , 1 ]
n = len (arr)
minimum_operations(arr, n)
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static void minimum_operations( int []arr, int n)
{
SortedSet< int > s = new SortedSet< int >();
for ( int i = 0; i < n; i++) {
s.Add(arr[i]);
}
int ops = 0;
for ( int i = n; i >= 1; i--) {
if (s.Contains(i)) {
s.Remove(i);
}
else {
ops++;
int it = s.Max;
it--;
if (it < 2 * i + 1) {
ops = -1;
break ;
}
s.Remove(it);
}
}
Console.Write(ops + "\n" );
}
public static void Main(String[] args)
{
int []arr = { 5, 4, 10, 8, 1 };
int n = arr.Length;
minimum_operations(arr, n);
}
}
|
Javascript
<script>
function minimum_operations(arr, n)
{
var s = new Set();
for ( var i = 0; i < n; i++) {
s.add(arr[i]);
}
var ops = 0;
for ( var i = n; i >= 1; i--) {
if (s.has(i)) {
s. delete (i);
}
else {
ops++;
var it = Math.max(...Array.from(s.values()));
it--;
if (it < 2 * i + 1) {
ops = -1;
break ;
}
s. delete (it);
}
}
document.write(ops + "<br>" );
}
var arr = [ 5, 4, 10, 8, 1 ];
var n = arr.length;
minimum_operations(arr, n);
</script>
|
Time Complexity: O(nlogn)
Auxiliary Space: O(n)