通过用相邻元素的XOR值替换,使阵列元素相等

216 阅读4分钟

通过用相邻元素的XOR值替换来使数组元素相等

给定一个由N个整数组成的数组 A[],任务是检查是否有可能减少至少长度为2的数组,使数组中的所有元素都相等。在一个操作中,选择任何索引i,用它们的XOR值替换A[i]和A[i+1]。

例子。

**输入。**A[] = {0, 2, 2}
输出。 YES
解释。 对i=0应用给定的操作(基于零的索引)。因此,将A[0]和A[1]替换为A[0]^A[1],即0^2->2,得到的数组是{2, 2},所有的元素都相等。

输入。 A[] = {2, 3, 1, 10}
输出。 NO
**解释。**这个数组不可能有全部相等的元素。

天真的方法。 上述问题可以通过观察来解决,即给定的数组可以被简化为具有两个相等元素或三个相等元素的数组。以下是解决上述问题的步骤。

  • 创建一个前缀数组,其中第i个索引存储数组A[]中从索引0i的元素的XOR
  • 案例1,数组可以减少到两个相等的元素
    • 假设得到的数组是_{X,X}_ 。由于数组中所有元素的XOR将保持不变,因此X^X=0=XOR( A[0...N-1]) 。这种情况可以通过检查数组中所有元素的XOR是否为0来轻松处理。
  • 案例2,数组可以减少到三个相等的元素
    • 这种情况可以通过遍历所有可能的**(i, j)值来处理,比如0<=i < j <=N-1,检查是否存在一个(i, j)值,使得XOR(A[0...i]) = XOR(A[i+1...j]) = XOR(A[j+1...N]) 。**

下面是上述方法的实现。

C++

// C++ Program of the above approach
#include <bits/stdc++.h>
using namespace std;
// Function to check if it is possible
// to make all the array elements equal
// using the given operation
void possibleEqualArray(int A[],int N)
{
// Stores the prefix XOR array
vector<int> pref(N);
pref[0] = A[0];
for (int i = 1; i < N; i++) {
// Calculate prefix[i]
pref[i] = pref[i - 1] ^ A[i];
}
// Case 1, check if the XOR of
// the input array is 0
if (pref[N - 1] == 0) {
cout <<"YES";
return;
}
// Case 2
// Iterate over all the ways to
// divide the array into three
// non empty subarrays
int cur_xor = 0;
for (int i = N - 1; i >= 0; i--) {
cur_xor ^= A[i];
for (int j = 0; j < i; j++) {
if (j) {
// XOR of Middle Block
int middle_xor
= pref[j - 1] ^ pref[i - 1];
// XOR of Left Block
int left_xor = pref[j - 1];
// XOR of Right Block
int right_xor = cur_xor;
if (left_xor == middle_xor
&& middle_xor == right_xor) {
cout <<"YES";
return;
}
}
}
}
// Not Possible
cout <<"NO";
}
// Driver Code
int main()
{
int A[] = { 0, 2, 2 };
int N =sizeof(A) /sizeof(int);
// Fucntion Call
possibleEqualArray(A, N);
return 0;
}

输出。

YES

时间复杂度。 O(N2)
空间复杂度。 O(N)

有效的方法。上 述方法可以通过以下观察进行优化:在数组可以减少到三个相等元素的情况下,结果数组可以表示为_{X, X, X}_ 。因为_,_ (X^X^X)=XOR(A[0...N-1]) ,这意味着X=XOR(A[0...N-1])。案例1的处理方法与天真的方法相同。情况2可以按以下方法解决。

  • cntcur_XOR初始化为0,并将A[]中所有元素的XOR存储在tot_XOR中。
  • 遍历数组A[],跟踪XOR直到当前元素在cur_XOR中。
  • 如果cur_XOR = tot_XOR,将cnt递增 1,并初始化cur_XOR = 0
  • 在遍历整个数组后,如果cnt的值**>2,就**可以用给定的操作使数组的所有元素相等。

下面是上述方法的实现。

C++

// C++ Program of the above approach
#include <bits/stdc++.h>
using namespace std;
// Function to check if it is possible
// to make all the array elements equal
// using the given operation
void possibleEqualArray(int A[],int N)
{
// Stores the XOR of all
// elements of array A[]
int tot_XOR = 0;
for (int i = 0; i < N; i++) {
tot_XOR ^= A[i];
}
// Case 1, check if the XOR of
// the array A[] is 0
if (tot_XOR == 0) {
cout <<"YES";
return;
}
// Case 2
// Maintains the XOR till
// the current element
int cur_XOR = 0;
int cnt = 0;
// Iterate over the array
for (int i = 0; i < N; i++) {
cur_XOR ^= A[i];
// If the current XOR is equall
// to the total XOR increment
// the count and initialize
// current XOR as 0
if (cur_XOR == tot_XOR) {
cnt++;
cur_XOR = 0;
}
}
// Print Answer
if (cnt > 2) {
cout <<"YES";
}
else {
cout <<"NO";
}
}
// Driver Code
int main()
{
int A[] = { 0, 2, 2 };
int N =sizeof(A) /sizeof(int);
// Function Call
possibleEqualArray(A, N);
return 0;
}

输出。

YES

时间复杂度。 O(N)
辅助空间。 O(1)

读者请注意!现在不要停止学习。掌握所有重要的DSA概念。 DSA自学课程以适合学生的价格获得所有重要的DSA概念,并成为行业的准备者。 要完成从学习语言到DS Algo以及更多的准备工作,请参考 完整的面试准备课程.

如果你想参加专家的现场课程 ,请参考 针对在职专业人士的DSA现场课程面向学生的竞争性编程直播.