检查给定数组的元素是否可以重新排列,使得 (arr[i] + i*K) % N = i 对于范围 [0, N-1] 中的所有 i 值
给定一个由N个正整数和一个整数K组成的数组arr[] ,任务是检查数组元素是否可以重新排列,使得(arr[i] + i*K) % N = i对于i的所有值范围[0, N-1] 。
例子:
Input: arr[] = {2, 1, 0}, K = 5
Output: Yes
Explanation: The given array can be rearranged to {0, 2, 1}. Hence the values after updation becomes {(0 + 0*5) % 3, (2 + 1*5) % 3, (1 + 2*5) % 3} => {0%3, 7%3, 11%3} => {0, 1, 2} having all elements equal to their indices in the array.
Input: arr[] = {1, 1, 1, 1, 1}, K = 5
Output: No
朴素方法:给定问题可以通过生成给定数组arr[]的所有可能排列来解决,并检查是否存在满足给定标准的任何此类排列。
时间复杂度: O(N*N!)
辅助空间: O(N)
高效方法:上述方法也可以借助使用递归的 Set 数据结构进行优化。以下是解决给定问题的一些观察结果:
- 每个数组元素arr[i]更新为(arr[i] + i*K) % N的事实。因此,值arr[i] % N和i*K % N可以独立计算。
- 如果 multiset A包含arr[i] % N的所有值,multiset B包含[0, N-1]范围内i的所有值的i*K % N的所有值,则生成元素的所有可能组合在A和B中并将(A[i] + B[i]) % N存储在一个集合中。如果结果集的大小为N ,则可以以所需的方式重新排列数组。
使用上述观察,可以通过以下步骤解决给定问题:
- 创建一个多重集A ,其中包含[0, N-1]范围内i的所有值的arr[i] % N的所有值。
- 类似地,创建一个多重集B包含i*K % N的所有值,用于范围[0, N-1]中的所有i值。
- 创建一个递归函数来迭代A和B中的所有整数对,将它们的和模N添加到集合C中,并递归调用剩余的元素。
- 如果在任何时候,集合的大小C = N ,则返回true ,否则返回false 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to check if it is possible
// to generate all numbers in range
// [0, N-1] using the sum of elements
// in the multiset A and B mod N
bool isPossible(multiset A,
multiset B,
set C, int N)
{
// If no more pair of elements
// can be selected
if (A.size() == 0 || B.size() == 0) {
// If the number of elements
// in C = N, then return true
if (C.size() == N) {
return true;
}
// Otherwise return false
else {
return false;
}
}
// Stores the value of final answer
bool ans = false;
// Iterate through all the pairs in
// the given multiset A and B
for (auto x : A) {
for (auto y : B) {
// Stores the set A without x
multiset _A = A;
_A.erase(_A.find(x));
// Stores the set B without y
multiset _B = B;
_B.erase(_B.find(y));
// Stores the set C with (x+y)%N
set _C = C;
_C.insert((x + y) % N);
// Recursive call
ans = (ans
|| isPossible(
_A, _B, _C, N));
}
}
// Return Answer
return ans;
}
// Function to check if it is possible
// to rearrange array elements such that
// (arr[i] + i*K) % N = i
void rearrangeArray(
int arr[], int N, int K)
{
// Stores the values of arr[] modulo N
multiset A;
for (int i = 0; i < N; i++) {
A.insert(arr[i] % N);
}
// Stores all the values of
// i*K modulo N
multiset B;
for (int i = 0; i < N; i++) {
B.insert((i * K) % N);
}
set C;
// Print Answer
if (isPossible(A, B, C, N)) {
cout << "YES";
}
else {
cout << "NO";
}
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 0 };
int K = 5;
int N = sizeof(arr) / sizeof(arr[0]);
rearrangeArray(arr, N, K);
return 0;
}
Python3
# Python3 program for the above approach
# Function to check if it is possible
# to generate all numbers in range
# [0, N-1] using the sum of elements
#+ in the multiset A and B mod N
def isPossible(A, B, C, N):
# If no more pair of elements
# can be selected
if(len(A) == 0 or len(B) == 0):
# If the number of elements
# in C = N, then return true
if(len(C) == N):
return True
# Otherwise return false
else:
return False
# Stores the value of final answer
ans = False
for x in A:
# Iterate through all the pairs in
# the given multiset A and B
for y in B:
# Stores the set A without x
_A = A
_A.remove(x)
# Stores the set A without y
_B = B
_B.remove(y)
# Stores the set A without x+y%N
_C = C
_C.add((x+y) % N)
# Recursive call
ans = (ans or isPossible(_A, _B, _C, N))
return ans
# Function to check if it is possible
# to rearrange array elements such that
# (arr[i] + i*K) % N = i
def rearrangeArray(arr, N, K):
# Stores the values of arr[] modulo N
A = []
for i in range(N):
A.append(arr[i] % N)
A.sort()
# Stores all the values of
# i*K modulo N
B = []
for i in range(N):
B.append((i*K) % N)
B.sort()
C = set()
# Print Answer
if isPossible(A, B, C, N):
print("YES")
else:
print("NO")
# Driver code
arr = [1, 2, 0]
K = 5
N = len(arr)
rearrangeArray(arr, N, K)
# This code is contributed by parthmanchanda81
Javascript
输出:
YES
时间复杂度: O(N*2 N )
辅助空间: O(1)