2 つの整数 a と b が与えられた場合、b が a の回転バージョンであることをどのように確認できますか?
たとえば、a = 0x01020304(バイナリで0000 0001 0000 0010 0000 0011 0000 0100)持っている場合、次の b 値は正しいです:
- ...
0x4080C1(右に 2 回転)0x810182(右に 1 回転)0x2040608(左に 1 回転)0x4080C10(左に 2 回転)- ...
2 つの整数 a と b が与えられた場合、b が a の回転バージョンであることをどのように確認できますか?
たとえば、a = 0x01020304(バイナリで0000 0001 0000 0010 0000 0011 0000 0100)持っている場合、次の b 値は正しいです:
0x4080C1(右に 2 回転)0x810182(右に 1 回転)0x2040608(左に 1 回転)0x4080C10(左に 2 回転)n ビット数の場合、KMP アルゴリズムを使用して、複雑さ O(n) の a の 2 つのコピー内で b を検索できます。
ループで実行する必要があると思います(c ++):
// rotate function
inline int rot(int x, int rot) {
return (x >> rot) | (x << sizeof(int)*8 - rot));
}
int a = 0x01020304;
int b = 0x4080C1;
bool result = false;
for( int i=0; i < sizeof(int)*8 && !result; i++) if(a == rot(b,i)) result = true;
一般的な場合 (任意の長さの整数を想定)、各回転を構成する単純な解は O(n^2) です。
しかし、あなたが効果的に行っているのは相関関係です。また、FFT を使用して周波数領域を経由することで、O(n log n) 時間で相関を行うことができます。
ただし、これは長さ 32 の整数ではあまり役に立ちません。
ここで回答を導き出すことにより、次のメソッド (C# で記述されていますが、Java でも同様です) がチェックを行います。
public static int checkBitRotation(int a, int b) {
string strA = Convert.ToString(a, 2).PadLeft(32, '0');
string strB = Convert.ToString(b, 2).PadLeft(32, '0');
return (strA + strA).IndexOf(strB);
}
戻り値が -1 の場合、b は a の回転バージョンではありません。それ以外の場合、b は a の回転バージョンです。
aorが定数 (またはループ定数) の場合b、すべての回転を事前に計算して並べ替え、定数ではないものをキーとしてバイナリ検索を実行できます。これはステップ数が少ないですが、実際にはステップが遅くなるため (二分探索は通常、予測が不十分な分岐で実装されます)、より良い方法ではない可能性があります。
ループ定数ではなく、実際に定数である場合は、さらにいくつかのトリックがあります。
a0または-1の場合、それは自明ですaは、次のようにテストできますb != 0 && (b & (b - 1)) == 0a、次のようなテストを実行できますror(b, tzcnt(b)) == ror(a, tzcnt(a))設定されたビットの連続したグループが 1 つしかない場合aは、次を使用できます。
int x = ror(b, tzcnt(b));
int y = ror(x, tzcnt(~x));
const int a1 = ror(a, tzcnt(a)); // probably won't compile
const int a2 = ror(a1, tzcnt(~a1)); // but you get the idea
return y == a2;
aが同じである場合、それを使用して、すべてをテストする代わりに特定のローテーションをスキップa == 0xAAAAAAAAできる場合があります。b == a || (b << 1) == apopcnt。もちろん、最初に述べたように、aとbが両方とも変数である場合、これは当てはまりません。
私は使用Integer.rotateLeftまたはrotateRight機能します
static boolean isRotation(int a, int b) {
for(int i = 0; i < 32; i++) {
if (Integer.rotateLeft(a, i) == b) {
return true;
}
}
return false;
}