Open In App

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

Last Updated : 03 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

  • Check If arr[] is already a permutation, then a possible answer will simply be (N+1)
  • Otherwise, find the sum of all the array elements.
  • Find all divisors of Srem and check which of the divisors satisfies the condition that it makes the array permutation upon applying the given modulo operation. 

Below is the implementation of the above approach.

C++




// 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;
}


Java




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




# 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


C#




// 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.


Javascript




// 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)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads