Open In App

Minimize operations to make Array a permutation

Last Updated : 01 Aug, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr of n integers. You want to make this array a permutation of integers 1 to n. In one operation you can choose two integers i (0 ≤ i < n) and x (x > 0), then replace arr[i] with arr[i] mod x, the task is to determine the minimum number of operations to achieve this goal otherwise return -1.

Note: A permutation is an array consisting of n distinct integers from 1 to n in arbitrary order.   

Examples:

Input: n = 2, arr = {1, 7}
Output:1
Explanation: In the first operation, you will choose i = 1, and x = 5, so the arr[1] will be (7%5) = 2, now the array {1, 2} is a permutation.

Input: n = 3, arr = {1, 5, 4}
Output: -1
Explanation: It’s not possible to make the 3rd element 2, or 3, so the answer will be -1.

Approach: This problem can be solved using Greedy Algorithm and Modulo Arithmetic.

The idea is to use the concept that any number x can be converted to y if y=x%m then y lies between 0 and ceil(x/2)-1. Thus, in the array, we just need to convert those numbers that are greater than n and those numbers that are less than or equal to n but are duplicates. Now just greedily pick a smaller number for conversion to a smaller element.

Steps that were to follow the above approach:

  • Create a vis array to mark those permutations which have been found in the array or have been made by using the given operation.
  • Sort the array to greedily pick smaller elements for conversion to smaller elements.
  • Create an array v to store the maximum possible number that can be made from numbers > n and duplicates of numbers ≤ n 
  • Make a variable j to iterate from 1 to n and check if we have made this permutation.
  • Iterate through vector v and initially iterate j to the permutation not found so far:
    • If (v[i] ≥ permutation not found) then this permutation can be made and keep iterating forward.
    • Otherwise making the permutation is not possible.

Below is the code to implement the above steps:

C++




// C++ code to implement the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to make permutation
int makePermutation(int n, vector<int>& arr)
{
    vector<int> vis(n + 1);
    sort(arr.begin(), arr.end());
    vector<int> v;
    for (int i = 1; i <= n; i++) {
        if (arr[i - 1] <= n) {
            if (vis[arr[i - 1]])
                v.push_back(arr[i - 1] & 1
                                ? arr[i - 1] / 2
                                : arr[i - 1] / 2 - 1);
            vis[arr[i - 1]] = 1;
        }
        else
            v.push_back(arr[i - 1] & 1
                            ? arr[i - 1] / 2
                            : arr[i - 1] / 2 - 1);
    }
    int j = 1;
    int ans = 0;
    for (int i = 0; i < v.size(); i++) {
        while (vis[j])
            j++;
 
        if (v[i] >= j)
            j++;
        else
            return -1;
        ans++;
    }
    return ans;
}
 
// Driver's code
int main()
{
 
    // Input array
    vector<int> arr = { 1, 7 };
 
    // Function call
    cout << makePermutation(2, arr) << endl;
 
    return 0;
}


Java




// Java  code to implement the above approach
import java.util.*;
 
public class Main {
 
  // Function to make permutation
  public static int makePermutation(int n,
                                    List<Integer> arr)
  {
    List<Integer> vis = new ArrayList<>(
      Collections.nCopies(n + 1, 0));
    Collections.sort(arr);
    List<Integer> v = new ArrayList<>();
    for (int i = 1; i <= n; i++) {
      if (arr.get(i - 1) <= n) {
        if (vis.get(arr.get(i - 1)) != 0)
          v.add((arr.get(i - 1) & 1) == 1
                ? arr.get(i - 1) / 2
                : arr.get(i - 1) / 2 - 1);
        vis.set(arr.get(i - 1), 1);
      }
      else
        v.add((arr.get(i - 1) & 1) == 1
              ? arr.get(i - 1) / 2
              : arr.get(i - 1) / 2 - 1);
    }
    int j = 1;
    int ans = 0;
    for (int i = 0; i < v.size(); i++) {
      while (vis.get(j) != 0)
        j++;
 
      if (v.get(i) >= j)
        j++;
      else
        return -1;
      ans++;
    }
    return ans;
  }
 
  // Driver's code
  public static void main(String[] args)
  {
 
    // Input array
    List<Integer> arr
      = new ArrayList<>(Arrays.asList(1, 7));
 
    // Function call
    System.out.println(makePermutation(2, arr));
  }
}


Python3




# Function to make permutation
def makePermutation(n, arr):
    vis = [0] * (n + 1)
    arr.sort()
    v = []
    for i in range(1, n + 1):
        if arr[i - 1] <= n:
            if vis[arr[i - 1]]:
                v.append(arr[i - 1] // 2 if arr[i - 1] & 1 else arr[i - 1] // 2 - 1)
            vis[arr[i - 1]] = 1
        else:
            v.append(arr[i - 1] // 2 if arr[i - 1] & 1 else arr[i - 1] // 2 - 1)
    j = 1
    ans = 0
    for i in range(len(v)):
        while vis[j]:
            j += 1
        if v[i] >= j:
            j += 1
        else:
            return -1
        ans += 1
    return ans
 
# Driver's code
if __name__ == '__main__':
    # Input array
    arr = [1, 7]
 
    # Function call
    print(makePermutation(2, arr))
 
# akashish__


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class GFG
{
    static int MakePermutation(int n, List<int> arr)
    {
        // Initialize a list to keep track of visited elements
        List<int> vis = new List<int>(new int[n + 1]);
 
        // Sort the input array
        arr.Sort();
 
        // Create a list to store modified values
        List<int> v = new List<int>();
 
        // Iterate over the input array
        for (int i = 1; i <= n; i++)
        {
            // Check if the current element is within the range
            if (arr[i - 1] <= n)
            {
                // If the element is already visited, add the modified
               // value to v
                if (vis[arr[i - 1]] != 0)
                    v.Add((arr[i - 1] & 1) != 0 ? arr[i - 1] / 2 :
                          arr[i - 1] / 2 - 1);
 
                // Mark the element as visited
                vis[arr[i - 1]] = 1;
            }
            else
            {
                // Add the modified value to v
                v.Add((arr[i - 1] & 1) != 0 ? arr[i - 1] / 2 : arr[i - 1] / 2 - 1);
            }
        }
 
        int j = 1;
        int ans = 0;
 
        // Iterate over the modified values in v
        for (int i = 0; i < v.Count; i++)
        {
            // Find the next available element
            while (vis[j] != 0)
                j++;
 
            // Check if the current modified value is greater
           // than or equal to the next available element
            if (v[i] >= j)
                j++;
            else
                return -1;
 
            // Increment the answer count
            ans++;
        }
 
        return ans;
    }
 
    static void Main(string[] args)
    {
        // Input array
        List<int> arr = new List<int> { 1, 7 };
 
        // Function call
        Console.WriteLine(MakePermutation(2, arr));
    }
}


Javascript




function makePermutation(n, arr) {
    const vis = new Array(n + 1).fill(0);
    arr.sort((a, b) => a - b);
    const v = [];
 
    for (let i = 1; i <= n; i++) {
        if (arr[i - 1] <= n) {
            if (vis[arr[i - 1]]) {
                v.push(arr[i - 1] & 1 ? arr[i - 1] / 2 : arr[i - 1] / 2 - 1);
            }
            vis[arr[i - 1]] = 1;
        } else {
            v.push(arr[i - 1] & 1 ? arr[i - 1] / 2 : arr[i - 1] / 2 - 1);
        }
    }
 
    let j = 1;
    let ans = 0;
 
    for (let i = 0; i < v.length; i++) {
        while (vis[j]) {
            j++;
        }
 
        if (v[i] >= j) {
            j++;
        } else {
            return -1;
        }
 
        ans++;
    }
 
    return ans;
}
 
// Driver's code
const arr = [1, 7];
console.log(makePermutation(2, arr));


Output

1



Time Complexity: O(N*log(N))
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads