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++ 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__ |
8
Time Complexity: O(N * F), where F is the maximum number of divisors.
Auxiliary Space: O(N)