📌  相关文章
📜  通过对 K 进行模运算,找到 K 以将给定的 Array 转换为排列

📅  最后修改于: 2022-05-13 01:56:09.087000             🧑  作者: Mango

通过对 K 进行模运算,找到 K 以将给定的 Array 转换为排列

给定一个包含N个整数的数组arr[] ,任务是找到一个值K ,使得运算arr[i] = arr[i] % K (0 ≤ i ≤ N-1) 使数组成为一个排列。如果不存在这样的K ,则打印 -1。

例子:

方法:给定的问题可以在以下观察的帮助下解决:

请按照以下步骤解决问题:

  • 检查如果arr[]已经是一个排列,那么可能的答案就是(N+1)
  • 否则,求所有数组元素的总和。
  • 找到S rem的所有除数并检查哪些除数满足在应用给定的模运算时进行数组排列的条件。

下面是上述方法的实现。

C++
// C++ code to implement above approach
 
#include 
using namespace std;
 
// Function to check is given set a
// permutation
bool is_given_set_permutation(set&
                                  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 findDivisors(int n)
{
    // Note that this loop runs till
    // square root
    vector 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 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 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 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;
}


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


输出
8

时间复杂度: O(N * F),其中 F 是除数的最大数量。
辅助空间: O(N)