以下计划的复杂性是什么?

时间:2011-06-06 08:44:02

标签: c++ c

以下程序的复杂程度如何?我认为它必须是O(n),因为有一个for循环运行了n次。

这是一个反转给定整数中的位的程序。

unsigned int reverseBits(unsigned int num)
{
    unsigned int NO_OF_BITS = sizeof(num) * 8;
    unsigned int reverse_num = 0;
    int i;
    for (i = 0; i < NO_OF_BITS; i++)
    {
        if((num & (1 << i)))
           reverse_num |= 1 << ((NO_OF_BITS - 1) - i);
    }
    return reverse_num;
}

上述计划的复杂程度如何?有人说实际的复杂性是O(log n),但我看不出原因。

5 个答案:

答案 0 :(得分:8)

考虑到您的上述计划,复杂性为O(1),因为8 * sizeof(unsigned int)是常量。您的程序将始终以恒定的时间运行。

但是,如果nNO_OF_BITS绑定,并且您将该数字设为算法参数(情况并非如此),那么复杂性将为O(n)

请注意,对于n位,num可能的最大值为2^n,在这种情况下,如果您希望将复杂性表示为允许的最大值的函数num,复杂度为O(log₂(n))O(log(N))

答案 1 :(得分:4)

O-notation描述了算法的时间或空间要求如何取决于输入的大小(表示为n),在n变得非常大的限制内。输入大小是表示输入所需的位数,而不是这些位可以表示的值的范围。

(正式地,将运行时间为t(n)的算法描述为O(f(n))意味着有一些N和一些C的常量t(n) <= C*f(n)所有n > N)。

此算法为每个输入位执行固定的工作量,因此时间复杂度为O(n)。它使用与输入大小相同的工作空间reverse_num(加上一些渐近变小的变量),因此空间复杂度也是O(n)

此特定实现对输入大小施加了限制,因此对时间和空间要求设置了固定的上限。一些答案说,意味着算法是O(1)。 O符号描述了算法,而不是任何特定的实现,如果在输入大小上加上限,则无意义。

答案 2 :(得分:1)

如果n是输入数,那么NO_OF_BITS是O(log n)(考虑一下:表示二进制数n,需要大约log2(n)位)。

编辑:让我根据其他回复和评论澄清一下。

首先,让n为输入数字(num)。澄清这一点非常重要,因为如果我们将n视为NO_OF_BITS,我们会得到不同的答案!

该算法概念 O(log n)。我们需要反转n的位。表示数字O(log n)需要n个比特,并且反转比特涉及每个比特的恒定工作量;因此复杂性为O(log n)

现在,实际上,C中的内置类型不能表示任意大小的整数。特别是,在此实现中使用unsigned int来表示输入,并且此类型限于固定数量的位(在大多数系统上为32)。此外,这个实现选择通过所有32位,而不是仅仅根据需要经历多个位(从最低位到高位1)。由于32是常量,因此技术的实现在O(1)时间内运行。

尽管如此,算法在概念上O(log n),如果输入是2^55迭代就足够了,如果输入是2^10,{ {1}}迭代就足够了,如果10代表的数字范围没有限制,输入为unsinged int,那么2^1000迭代就是必要的。< / p>

在任何情况下,此算法都不会1000(除非我们将O(n)定义为n,在这种情况下它是)。

答案 3 :(得分:1)

如果n == num,复杂度是常数O(1),因为循环总是运行固定的次数。空间复杂度也是O(1),因为它不依赖于输入

答案 4 :(得分:0)

你需要清楚n是什么。如果n是num,那么您的代码当然是O(log n)NO_OF_BITS ~= log_2(n) * 8

另外,当你处理固定大小的值时,整个事情是O(1)。当然,如果您将此视为更一般的概念并且可能对其进行扩展,那么可以在更一般的上下文中将其视为O(log n),您希望将其扩展到固定位数之外。< / p>