Open In App

Find K to convert given Array into permutation by performing modulo by K

Given an array arr[] of N integers, the task is to find a value K such that the operation arr[ i ] = arr[ i ] % K (0 ≤ i ≤ N-1), makes the array a permutation. If no such K exists print -1.

A sequence of N integers is called permutation if it contains all integers from 1 to N exactly once.



Examples:  

Input: N = 3, arr[ ] = {2, 7, 1}
Output: 4
Explanation: [2%4, 7%4, 1%4] = [2, 3, 1] which is a permutation of N = 3.



Input: N = 5, arr[ ] = {18, 81, 29, 36, 11}
Output: 8
Explanation: [18%8, 81%8, 29%8, 36%8, 11%8] = [2, 1, 5, 4, 3] which is a permutation of N = 5.

Input: N = 2, arr[ ] = {2, 2}
Output: -1

 

Approach: The given problem can be solved with the help of the following observation:

If the given arr[] has at least one repeated element, it can never become a permutation. So, all arr[i] must be unique in arr[]. If not, then print -1.

If there exists such K. So, we express each arr[i] in terms of K as given:

  • A1 = Q1*K + R1
    A2 = Q2*K + R2
    A3 = Q3*K + R3
    . . . . . . 
    AN = QN*K + RN
  • To be a valid K, (R1, R2, R3 …. RN) must be a permutation from 1 to N
  • Hence, Σ arr[i] = (Σ Qi)*K + (Σ Ri). 
    • We know (Σ Ri) = (N*(N+1))/2 = Sr (Say).
    • let S = (Q’) *K +Sr, where Q’ = (Σ Qi).
    • let Srem = (Q’) *K = S – Sr = (sum of all array elements) – (N*(N+1))/2.
  • It is evident that K must a divisor of Srem.

Follow the steps mentioned below to solve the problem:

Below is the implementation of the above approach.




// C++ code to implement above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to check is given set a
// permutation
bool is_given_set_permutation(set<int>&
                                  hash,
                              int N)
{
    int last_element = *hash.rbegin();
    if (hash.size() == N
        && last_element == N) {
        return true;
    }
    return false;
}
 
// Function to find the divisors
vector<int> findDivisors(int n)
{
    // Note that this loop runs till
    // square root
    vector<int> divisors;
 
    for (int i = 1; i <= sqrt(n); i++) {
        if (n % i == 0) {
            // If divisors are equal,
            // push only one
            if (n / i == i)
                divisors.push_back(i);
 
            // Otherwise push both
            else {
                divisors.push_back(i);
                divisors.push_back(n / i);
            }
        }
    }
    return divisors;
}
 
// Function returns if the current divisor
// is the required answer
bool is_current_divisor_answer(int arr[],
                               int N, int div)
{
    set<int> hash;
    for (int i{ 0 }; i < N; i++) {
        hash.insert(arr[i] % div);
    }
    return is_given_set_permutation(hash, N);
}
 
// Function to the number d which on applying
// arr[i]%d to each element makes the array
// a permutation
int number_to_make_permutation(int arr[], int N)
{
    // Set to store elements of arr[]
    set<int> hash;
 
    for (int i{ 0 }; i < N; i++) {
        hash.insert(arr[i]);
    }
 
    if (hash.size() != N) {
 
        // When hash size !=N, there are
        // repeating elements in arr[].
        // So it can never be a permutation
        return -1;
    }
 
    if (is_given_set_permutation(hash, N)) {
 
        // Given arr[] is already a
        // permutation
        return (N + 1);
    }
    int total_sum{ 0 };
 
    // Loop to find the sum of the array
    for (int i{ 0 }; i < N; i++) {
        total_sum += arr[i];
    }
 
    int sum_of_permutation
        = (N * (N + 1)) / 2;
    int remaining_sum = total_sum - sum_of_permutation;
    vector<int> divisors = findDivisors(
        remaining_sum);
 
    // Loop to check if any divisor
    // satisfies the condition
    for (int i{ 0 }; i < divisors.size();
         i++) {
        // A divisor <= N can
        // never be an answer
        if (divisors[i] <= N)
            continue;
        if (is_current_divisor_answer(arr, N,
                                      divisors[i])) {
            return divisors[i];
        }
    }
    return -1;
}
 
// Driver code
int main()
{
    int arr[] = { 18, 81, 29, 36, 11 };
    int N = sizeof(arr) / sizeof(int);
 
    // Function call
    cout << number_to_make_permutation(arr, N);
    return 0;
}




import java.util.*;
import java.io.*;
 
// Java program for the above approach
class GFG{
 
  // Function to check is given set a
  // permutation
  public static Boolean is_given_set_permutation(SortedSet<Integer> hash, int N)
  {
    int last_element = hash.last();
    if (hash.size() == N && last_element == N) {
      return true;
    }
    return false;
  }
 
  // Function to find the divisors
  public static ArrayList<Integer> findDivisors(int n)
  {
    // Note that this loop runs till
    // square root
    ArrayList<Integer> divisors = new ArrayList<Integer>();
 
    for (int i = 1 ; i <= Math.floor(Math.sqrt(n)) ; i++) {
      if (n % i == 0) {
        // If divisors are equal,
        // push only one
        if (n / i == i)
          divisors.add(i);
 
        // Otherwise push both
        else {
          divisors.add(i);
          divisors.add(n / i);
        }
      }
    }
    return divisors;
  }
 
  // Function returns if the current divisor
  // is the required answer
  public static Boolean is_current_divisor_answer(int arr[], int N, int div)
  {
    SortedSet<Integer> hash = new TreeSet<Integer>();
    for (int i = 0 ; i < N ; i++) {
      hash.add(arr[i] % div);
    }
    return is_given_set_permutation(hash, N);
  }
 
  // Function to the number d which on applying
  // arr[i]%d to each element makes the array
  // a permutation
  public static int number_to_make_permutation(int arr[], int N){
 
    // Set to store elements of arr[]
    SortedSet<Integer> hash = new TreeSet<Integer>();
 
    for (int i = 0 ; i < N ; i++) {
      hash.add(arr[i]);
    }
 
    if (hash.size() != N) {
 
      // When hash size !=N, there are
      // repeating elements in arr[].
      // So it can never be a permutation
      return -1;
    }
 
    if (is_given_set_permutation(hash, N)) {
 
      // Given arr[] is already a
      // permutation
      return (N + 1);
    }
    int total_sum =  0;
 
    // Loop to find the sum of the array
    for (int i = 0 ; i < N ; i++) {
      total_sum += arr[i];
    }
 
    int sum_of_permutation = (N * (N + 1)) / 2;
    int remaining_sum = total_sum - sum_of_permutation;
    ArrayList<Integer> divisors = findDivisors(remaining_sum);
 
    // Loop to check if any divisor
    // satisfies the condition
    for (int i = 0 ; i < divisors.size(); i++) {
      // A divisor <= N can
      // never be an answer
      if (divisors.get(i) <= N)
        continue;
      if (is_current_divisor_answer(arr, N, divisors.get(i))) {
        return divisors.get(i);
      }
    }
    return -1;
  }
 
  // Driver code
  public static void main(String args[])
  {
    int arr[] = {18, 81, 29, 36, 11};
    int N = arr.length;
 
    System.out.println(number_to_make_permutation(arr, N));
  }
}
 
// This code is contributed by subhamgoyal2014.




# Python3 code to implement above approach
import math
 
# Function to check is given set a
# permutation
def is_given_set_permutation(hash, N):
 
    last_element = list(hash)[len(hash) - 1]
    if (len(hash) == N and last_element == N):
        return True
 
    return False
 
# Function to find the divisors
def findDivisors(n):
 
    # Note that this loop runs till
    # square root
    divisors = []
 
    for i in range(1, int(math.sqrt(n)) + 1):
        if (n % i == 0):
            # If divisors are equal,
            # push only one
            if (n // i == i):
                divisors.append(i)
 
            # Otherwise push both
            else:
                divisors.append(i)
                divisors.append(n // i)
 
    return divisors
 
# Function returns if the current divisor
# is the required answer
def is_current_divisor_answer(arr, N, div):
    hash = set()
    for i in range(0, N):
        hash.add(arr[i] % div)
 
    return is_given_set_permutation(hash, N)
 
# Function to the number d which on applying
# arr[i]%d to each element makes the array
# a permutation
def number_to_make_permutation(arr, N):
 
    # Set to store elements of arr[]
    hash = set()
 
    for i in range(0, N):
        hash.add(arr[i])
 
    if (len(hash) != N):
 
        # When hash size !=N, there are
        # repeating elements in arr[].
        # So it can never be a permutation
        return -1
 
    if (is_given_set_permutation(hash, N)):
 
        # Given arr[] is already a
        # permutation
        return (N + 1)
 
    total_sum = 0
 
    # Loop to find the sum of the array
    for i in range(0, N):
        total_sum += arr[i]
 
    sum_of_permutation = (N * (N + 1)) // 2
    remaining_sum = total_sum - sum_of_permutation
    divisors = findDivisors(remaining_sum)
 
    # Loop to check if any divisor
    # satisfies the condition
    for i in range(0, len(divisors)):
        # A divisor <= N can
        # never be an answer
        if (divisors[i] <= N):
            continue
        if (is_current_divisor_answer(arr, N, divisors[i])):
            return divisors[i]
 
    return -1
 
# Driver code
if __name__ == "__main__":
    arr = [18, 81, 29, 36, 11]
    N = len(arr)
 
    # Function call
    print(number_to_make_permutation(arr, N))
 
    # This code is contributed by rakeshsahni




// Include namespace system
using System;
using System.Collections.Generic;
 
// C# program for the above approach
public class GFG
{
    // Function to check is given set a
    // permutation
    public static bool is_given_set_permutation(SortedSet<int> hash, int N)
    {
        var last_element = hash.Max;
        if (hash.Count == N && last_element == N)
        {
            return true;
        }
        return false;
    }
    // Function to find the divisors
    public static List<int> findDivisors(int n)
    {
        // Note that this loop runs till
        // square root
        var divisors = new List<int>();
        for (int i = 1; i <= Math.Floor(Math.Sqrt(n)); i++)
        {
            if (n % i == 0)
            {
                // If divisors are equal,
                // push only one
                if ((int)(n / i) == i)
                {
                    divisors.Add(i);
                }
                else
                {
                    divisors.Add(i);
                    divisors.Add((int)(n / i));
                }
            }
        }
        return divisors;
    }
    // Function returns if the current divisor
    // is the required answer
    public static bool is_current_divisor_answer(int[] arr, int N, int div)
    {
        var hash = new SortedSet<int>();
        for (int i = 0; i < N; i++)
        {
            hash.Add(arr[i] % div);
        }
        return GFG.is_given_set_permutation(hash, N);
    }
    // Function to the number d which on applying
    // arr[i]%d to each element makes the array
    // a permutation
    public static int number_to_make_permutation(int[] arr, int N)
    {
        // Set to store elements of arr[]
        var hash = new SortedSet<int>();
        for (int i = 0; i < N; i++)
        {
            hash.Add(arr[i]);
        }
        if (hash.Count != N)
        {
            // When hash size !=N, there are
            // repeating elements in arr[].
            // So it can never be a permutation
            return -1;
        }
        if (GFG.is_given_set_permutation(hash, N))
        {
            // Given arr[] is already a
            // permutation
            return (N + 1);
        }
        var total_sum = 0;
        // Loop to find the sum of the array
        for (int i = 0; i < N; i++)
        {
            total_sum += arr[i];
        }
        var sum_of_permutation = (int)((N * (N + 1)) / 2);
        var remaining_sum = total_sum - sum_of_permutation;
        var divisors = GFG.findDivisors(remaining_sum);
        // Loop to check if any divisor
        // satisfies the condition
        for (int i = 0; i < divisors.Count; i++)
        {
            // A divisor <= N can
            // never be an answer
            if (divisors[i] <= N)
            {
                continue;
            }
            if (GFG.is_current_divisor_answer(arr, N, divisors[i]))
            {
                return divisors[i];
            }
        }
        return -1;
    }
   
    // Driver code
    public static void Main(String[] args)
    {
        int[] arr = {18, 81, 29, 36, 11};
        var N = arr.Length;
        Console.WriteLine(GFG.number_to_make_permutation(arr, N));
    }
}
 
 // This code is contributed by aadityaburujwale.




// Function to check is given set a
// permutation
function is_given_set_permutation(hash, N) {
    const sortedArr = Array.from(hash).sort((a, b) => a - b);
    hash = new Set(sortedArr);
    let last_element = Array.from(hash)[hash.size - 1];
    if (hash.size == N && last_element == N) {
        return true;
    }
    return false;
}
 
// Function to find the divisors
function findDivisors(n) {
    // Note that this loop runs till
    // square root
    let divisors = [];
 
    for (let i = 1; i <= Math.sqrt(n); i++) {
        if (n % i == 0) {
            // If divisors are equal,
            // push only one
            if (n / i == i) {
                divisors.push(i);
            }
            // Otherwise push both
            else {
                divisors.push(i);
                divisors.push(Math.floor(n / i));
            }
        }
    }
    return divisors;
}
 
// Function returns if the current divisor
// is the required answer
function is_current_divisor_answer(arr, N, div) {
    let hash = new Set();
    for (let i = 0; i < N; i++) {
        hash.add(arr[i] % div);
    }
    return is_given_set_permutation(hash, N);
}
 
// Function to the number d which on applying
// arr[i]%d to each element makes the array
// a permutation
function number_to_make_permutation(arr, N) {
    // Set to store elements of arr[]
    let hash = new Set();
 
    for (let i = 0; i < N; i++) {
        hash.add(arr[i]);
    }
 
    if (hash.size != N) {
        // When hash size !=N, there are
        // repeating elements in arr[].
        // So it can never be a permutation
        return -1;
    }
 
    if (is_given_set_permutation(hash, N)) {
        // Given arr[] is already a
        // permutation
        return N + 1;
    }
    let total_sum = 0;
 
    // Loop to find the sum of the array
    for (let i = 0; i < N; i++) {
        total_sum += arr[i];
    }
 
    let sum_of_permutation = (N * (N + 1)) / 2;
    let remaining_sum = total_sum - sum_of_permutation;
    let divisors = findDivisors(
        remaining_sum);
 
    // Loop to check if any divisor
    // satisfies the condition
    for (let i = 0; i < divisors.length; i++) {
        // A divisor <= N can
        // never be an answer
        if (divisors[i] <= N)
            continue;
        if (is_current_divisor_answer(arr, N,
            divisors[i])) {
            return divisors[i];
        }
    }
    return -1;
}
 
// Driver code
 
let arr = [18, 81, 29, 36, 11];
let N = arr.length;
 
// Function call
console.log(number_to_make_permutation(arr, N));
 
// This code is contributed by akashish__

Output
8

Time Complexity: O(N * F), where F is the maximum number of divisors.
Auxiliary Space: O(N)


Article Tags :