C++でXORが等しくなる2つの部分配列を持つトリプレットの個数を数える方法
問題概要
整数型の配列 arr が与えられたとします。ここで、(0 <= i < j <= k < N) を満たす3つのインデックス i、j、k を選ぶことを考えます(N は配列のサイズです)。このとき、a と b の値はそれぞれ次のように定義されます。
a = arr[i] XOR arr[i + 1] XOR ... XOR arr[j - 1]
b = arr[j] XOR arr[j + 1] XOR ... XOR arr[k]
この問題の目的は、a と b が等しくなるようなトリプレット (i, j, k) の総数を求めることです。
例として、入力が [2,3,1,6,7] の場合を考えてみましょう。このとき出力は 4 となります。条件を満たすトリプレットは (0,1,2)、(0,2,2)、(2,3,4)、(2,4,4) の4つです。
解法のアプローチ
この問題は、マップ(連想配列)を活用することで効率的に解くことができます。手順は以下の通りです。
結果を格納する変数 ret を 0 で初期化する
n を配列 arr のサイズとする
i を 1 から開始し、i < n の間、i を1ずつ増やしながら以下を繰り返す
マップ m を定義する
x1 := 0、x2 := 0 で初期化する
j を i - 1 から開始し、j >= 0 の間、j を1ずつ減らしながら、x1 に arr[j] の XOR を累積し、m[x1] のカウントを1増やす
j を i から開始し、j < n の間、j を1ずつ増やしながら、x2 に arr[j] の XOR を累積し、ret に m[x2] の値を加算する
最後に ret を返す
このアプローチのポイントは、境界位置 i ごとに、左側の部分配列で作られる各 XOR 値の出現回数をマップに記録しておき、右側の部分配列の XOR 値と照合することで、a = b となる組み合わせを効率よく数えられる点です。計算量は O(n²) となり、すべての組み合わせを素朴に調べる O(n³) の方法よりも高速に動作します。
実装例
理解を深めるために、以下のC++による実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int countTriplets(vector<int>& arr) {
int ret = 0;
int n = arr.size();
for (int i = 1; i < n; i++) {
map<int, int> m;
int x1 = 0;
int x2 = 0;
for (int j = i - 1; j >= 0; j--) {
x1 = x1 ^ arr[j];
m[x1]++;
}
for (int j = i; j < n; j++) {
x2 = x2 ^ arr[j];
ret += m[x2];
}
}
return ret;
}
};
main(){
Solution ob;
vector<int> v = {2,3,1,6,7};
cout << (ob.countTriplets(v));
}入力
{2,3,1,6,7}出力
4
-
【C++】ソート済み配列から等差数列(AP)を形成するすべてのトリプレットを出力する方法
この問題では、ソートされた数値の配列が与えられ、その中から等差数列(AP:Arithmetic Progression)を形成するトリプレット(3つの組)をすべて見つけ出します。 等差数列とは、隣り合う項同士の差(公差)が常に一定である数列のことです。 問題例 入力 :array = {2 , 5 , 7, 8 , 9 , 10}出力 :2 5 85 7 97 8 98 9 10 単純なアプローチ 最もシンプルな解決策は、三重のループを回してすべてのトリプレットを列挙し、それぞれが等差数列を成すかどうかを確認する方法です。しかし、この方法の計算量は O(n³) のオーダーとなり、配列のサイズが
-
【C++】2つのバイナリ配列のXORを別の配列と等しくするための最小フリップ回数
問題文 0と1のみから構成される、長さnの3つの配列が与えられます。求めたいのは、1つ目と2つ目の配列のビットをできるだけ少ない回数反転(フリップ)させて、「1つ目の配列のi番目の要素」と「2つ目の配列のi番目の要素」のXORが、「3つ目の配列のi番目の要素」と一致するようにするための最小反転回数です。 ただし、配列1については最大p個、配列2については最大q個までしかビットを反転できません。また、配列の要素を並べ替えることは許されていません。 ここでは、p = 2、q = 5 の場合を例に考えてみましょう。 arr1[] = {1, 0, 1, 1, 0, 1, 0} arr2[] = {