对于作业,我需要找到一种算法,可以测试数字n是时间O(log log n)时间的4的幂。我不知道如何处理这个问题,也不知道哪些数据结构或算法是合适的。有没有人对如何解决这个问题有任何建议?
答案 0 :(得分:4)
O(log log n)
要求有点奇怪。如果你正在处理无界的整数,并且这些整数用通常的二进制形式表示,那么你真的无法检查n
的所有位。在这种情况下,你不可能比O(log n)
做得更好。另一方面,如果您只计算基本操作,可以在O(1)
时间内完成。
这是一些Python代码:
>>> def is_power_of_four(n):
... return n & (n-1) == 0 and n % 3 == 1
...
>>> [n for n in range(-10**6, 10**6) if is_power_of_four(n)]
[1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144]
就位操作而言,此算法为O(log n)
。就操作计数而言,它是O(1)
。说明:n & (n-1)
是应用于n
和n-1
的{{3}}操作。当且仅当n
为2的幂或n == 0
时,该值为零。在两个权力中,四个权力的余数1
模3
,而其他两个权力的余数2
。余数测试也方便地排除案例n == 0
。
如果您还想知道四个n
的次幂,而不仅仅是确定n
是否为4的幂,那么这是一个不同的问题,templatetypedef已经给出了有效的答案。
答案 1 :(得分:4)
如果你知道单词大小,你可以比O(log log N)做得更好 - 实际上,你可以在O(1)中用它编译下来的4个机器指令。例如,如果假设32位整数,则可以执行以下操作:
int is_power_of_4(int x) {
return ( (x & (-x)) & 0x55555554 ) == x;
}
对于不同的字大小,只需更改常量。
x & (-x)
技巧是一个众所周知的黑客,它返回的数字只是x中最不重要的1位。 & 0x5554
然后屏蔽两个奇数幂,然后比较原始失败,如果x中有任何其他设置位。
答案 2 :(得分:2)
我将假设数字表示为固定宽度的整数,它允许在时间O(1)内完成基本操作,如比较,加法,乘法等。
请注意,如果您有一个数字n,则该数字n中包含O(log n)位。如果我们让b是数字中的位数,那么期望的运行时间将是O(log b)。换句话说,我们希望找到一些函数,其运行时间是数字中位数的对数。
由于我们试图检查数字是否为4的幂,我们试图查看该数字是否具有某个数字k的形式4 k 。这是我们可以用来做到这一点的一种可能方法:
计算4 1 ,4 2 ,4 4 ,4 8 ,4 16 ,...,4 2 x 直到我们找到一个大于数字n的数字。这意味着如果n是4的幂,则它必须是夹在4 0 和4 2 x 之间的4的幂。由于以下原因,此步骤最终将采用O(log log n)时间:数字n可写为4 log 4 n 。一旦4 2 x ≥4 log 4 n ,上述过程就会终止 x ≥log 4 n,当x≥log 2 log 4 n时发生。因此,只有O(log log n)总迭代次数,每次迭代需要时间O(1)。
在[0,2 x ]范围内进行二元搜索,以确定k的哪个值(如果有)满足n = 4 k 。此步骤的运行时间为O(x),因为在大小为2 x 的范围内,二进制搜索将花费时间O(log 2 x )= O(x) 。而且,我们知道x = O(log n)。在步骤(1)中,我们保持指数加倍,直到它超过log 4 n的值。这意味着在最坏的情况下,x可以是2 log 4 x,因此x = O(log n)。因此,此步骤也需要O(log log n)时间。
由于步骤(1)和(2)各自花费时间O(log log n),因此总体时间复杂度为O(log log n)。
注意:您可以将此问题视为n的对数上的“猜数字游戏”的变体。一个经典的采访问题是“我正在考虑一个自然数n,你应该试着猜测它。”您可以使用上述方法在O(log n)时间内解决它。在这种情况下,您试图猜测4的指数是否正常,因此您可以将该过程应用于数字的对数以获得O的运行时间(log log n)。
希望这有帮助!
答案 3 :(得分:0)
对于无符号整数,您可以使用:
bool is_pow4(DWORD x)
{
/*
4^0 = 1 = 00000000001b
4^1 = 4 = 00000000100b
4^2 = 16 = 00000010000b
4^3 = 64 = 00001000000b
4^4 = 256 = 00100000000b
4^5 = 1024 = 10000000000b
-------------------------
or together 10101010101b
negate 01010101010b = A....AAAh
*/
if (!x) return false;
if (DWORD(x&(x-1))) return false; // not power of 2 (more than 1 bit is set)
return !(x&0xAAAAAAAA); // not setted any bit from negated mask
}
这里也解决了非常类似的问题:https://stackoverflow.com/a/19888301/2521214
PS。复杂性与x - ,&
答案 4 :(得分:0)
使用面膜稍微便宜一些。
#include <stdio.h>
#include <string.h>
int main ()
{
int x;
int mask;
memset(&mask, 0x55, sizeof(int));
scanf("%d",&x);
if ((x) && ((x & (x-1)) == 0) && (x & mask))
printf("Power of four\n");
else
printf("Not power of four\n");
return (0);
}
答案 5 :(得分:0)
在此提供机器便携式解决方案。此解决方案不需要任何预先计算的数字,也不会对机器的位宽做出任何假设。
bool isPowerOfFour(int num) {
int s = ceil(sqrt(num));
// s > 0 makes sure 0 is not power of four
// 4^x -> 2^(2x) so sqrt of it should be 2^x all we need to do is to tell whether the sqrt is a power or two
// but firstly we need to make sure sqrt(num) is an integer so we use s*s == num
// then use (s&(s-1)) == 0 to tell whether it is a power of 2
return s > 0 && s*s == num && (s&(s-1)) == 0;
}