Python 用递归计算大O符号

Python 用递归计算大O符号,python,python-3.x,big-o,notation,Python,Python 3.x,Big O,Notation,我试图理解大O符号最坏情况下的运行时。 但我还是不太明白 这是我最近写的一些代码: def g(n): if n==0: return 1 elif n==1: return 2 else: n_div=n//2 n_mod=n%2 return g(n_div)*g(n_mod) 所以我希望我至少是对的: def g(n): if n==0: return 1 以

我试图理解大O符号最坏情况下的运行时。 但我还是不太明白

这是我最近写的一些代码:

def g(n):
    if n==0:
        return 1
    elif n==1:
        return 2
    else:
        n_div=n//2
        n_mod=n%2
        return g(n_div)*g(n_mod)
所以我希望我至少是对的:

def g(n):
    if n==0:
        return 1
以及:

都是O(1),所以是常数

但是
else
部分呢

是O(n)因为它取决于我选择的
n


有人能解释一下
其他部分的复杂程度吗?

您已经注意到,您可以将函数分为3种情况,并且已经确定前2种是O(1)。第三个部分稍微复杂一些,但您也可以将其分为两部分

递归显然发生在:

g(n//2)*g(n%2)
我们可以立即看到,
n%2
将计算为0或1,这将再次解决前两种情况之一,因此我们可以忽略这一点。留给我们的是
g(n//2)
。通过将其重写为打印循环并检查输出,您将注意到:

>>> n = 37
>>> while n > 1:
...     n //= 2
...     print(n)
...
18
9
4
2
1
正如您所看到的,每次项都会减少一半,在递归中也会发生同样的情况。这是对数

因此,此函数的最坏情况是O(logn)


通过查看,您可以进一步了解logn在Big-O表示法中的实际含义。

O表示法实际上并不适用于程序的一部分。它确实测量了随着输入大小的增加,运行时间增加的方式。在这种情况下,耗时部分是最终的else部分

您需要了解这对您的程序是如何起作用的。这里有一个简单的实证分析,应该对你有所帮助。如果我们对程序进行一些测试,以打印出对于给定输入,最终的
else
部分运行了多少次,我们就会得到这个结果

   n | times
-----+-----
   2 | 1
   4 | 2
   8 | 3
  16 | 4
  32 | 5
  64 | 6
 128 | 7
 256 | 8
 512 | 9
1024 | 10
2048 | 11
4096 | 12
8192 | 13
如果你画这个,你会看到这样的东西


您可以看到,随着输入大小的增加,调用的数量也会增加,但呈次线性。事实上,它是对数的,因为你的
n
在循环的每次迭代中减少50%。

有没有一个函数来计算二进制代码中的1?
   n | times
-----+-----
   2 | 1
   4 | 2
   8 | 3
  16 | 4
  32 | 5
  64 | 6
 128 | 7
 256 | 8
 512 | 9
1024 | 10
2048 | 11
4096 | 12
8192 | 13