不适用于相同的a和b。您应该从i = 0开始循环。
是的,我的错。
所有Id的拳头宁愿使用unsigned int进行任何合理的位操作,然后CHAR_BIT比8(或者只是std::numeric_limits::digits而不是整个sizeof疯狂)更适合一些,但是好的,那些只是微小的缺陷。通常,这可能仍然是最好的方法。
在一般情况下(假定任意长度的整数),组成每次旋转的天真解是O(n ^ 2)。
但是,您实际上正在做的是相关性。您可以通过使用FFT在频域中进行O(n log n)时间的相关。
尽管这对于长度为32的整数没有太大帮助。
听起来很有趣。你可以再详细一点吗??
但是,这是错误的:考虑到每次旋转仅O(N)。您旋转a来匹配b,但是b本身没有旋转。
@MSalters:有O(N)个旋转和比较,但每个比较也是O(N)。
我认为这是谈论复杂性没有用的情况之一。如果问题是关于BigIntegers,我将支持您。但是在这种情况下,CPU不会逐位比较,因此O(N ^ 2)似乎对我有些误导。
@HonzaBrabec:我明白您的意思了,但是我之所以发布此一般性答复,是因为OP专门说了"整数"而不是" ints";我可能对此已经读得太多了...
通过在此处得出答案,以下方法(用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的旋转版本。
嗯,在将整个对象转换成字符串并进行字符串搜索之前,我宁愿执行32次简单的整数移位循环。
+1是我从未想到的巧妙技巧。可能比蛮力逼迫慢,但仍然很整洁。
您可以使用std::bitset<32>::to_string()&#xff0c;但不多。
如果a或b是常数(或循环常数)&#xff0c;则可以预先计算所有旋转并将其排序&#xff0c;然后使用非常数作为键进行二进制搜索。那是更少的步骤&#xff0c;但是这些步骤在实践中比较慢(二进制搜索通常是通过预测错误的分支来实现的)&#xff0c;因此可能不会更好。
如果它确实是一个常量&#xff0c;而不是一个循环常量&#xff0c;那么还有一些技巧&#xff1a;
如果a为0或-1&#xff0c;则不重要
如果a仅设置了1位&#xff0c;则可以像b !&#61; 0 && (b & (b - 1)) &#61;&#61; 0一样进行测试
如果a设置了2位&#xff0c;则可以像ror(b, tzcnt(b)) &#61;&#61; ror(a, tzcnt(a))那样进行测试
如果a仅具有一组连续的设置位&#xff0c;则可以使用
int x &#61; ror(b, tzcnt(b));
int y &#61; ror(x, tzcnt(~x));
const int a1 &#61; ror(a, tzcnt(a)); // probably won&#39;t compile
const int a2 &#61; ror(a1, tzcnt(~a1)); // but you get the idea
return y &#61;&#61; a2;
如果a的许多旋转相同&#xff0c;则您可以使用它来跳过某些旋转而不是全部测试&#xff0c;例如&#xff0c;如果a &#61;&#61; 0xAAAAAAAA&#xff0c;则测试可以是b &#61;&#61; a || (b <<1) &#61;&#61; a
除了popcnt测试之外&#xff0c;您还可以比较常数的最小和最大旋转以进行快速的预测试。
当然&#xff0c;正如我在一开始所说的&#xff0c;当a和b都是变量时&#xff0c;这都不适用。
我会使用Integer.rotateLeft或rotateRight func
static boolean isRotation(int a, int b) {
for(int i &#61; 0; i <32; i&#43;&#43;) {
if (Integer.rotateLeft(a, i) &#61;&#61; b) {
return true;
}
}
return false;
}
您只需要在32个可能的值中进行30个测试。尽管x &#61;&#61; y是否表示没有旋转是有争议的&#xff0c;但您仍然缺少至少一种情况。
好吧&#xff0c;另一方面&#xff0c;b不是a的旋转形式
这就是为什么我说这是有争议的。但是&#xff0c;即使您认为第0(也就是第32)旋转应返回false&#xff0c;您仍然会错过第31旋转。
我同意&#xff0c;这是一个错误&#xff0c;已修复
输入是a和b&#xff0c;但是您检查x和y&#xff1f;
已经将其更改为a和b
我的意思是isRotation(int a&#xff0c;int b)vs(Integer.rotateLeft(x&#xff0c;i)&#61;&#61; y)