具有两个调用的递归函数的时间复杂度

时间:2013-12-07 22:18:15

标签: python complexity-theory time-complexity

考虑以下代码:

def count_7(lst):
    if len(lst) == 1:
        if lst[0] == 7:
            return 1
        else:
            return 0

    return count_7(lst[:len(lst)//2]) + count_7(lst[len(lst)//2:])

注意:切片操作将被视为O(1)。

所以,我的语言告诉我它是O(n * logn),但我正在努力证明它是科学的。
很高兴能帮忙!

3 个答案:

答案 0 :(得分:3)

好的,数学上(有点像)我得到这样的东西:

T(n) = 2T(n/2) + c
T(1) = 1

推广等式:

T(n) = 2^k * T(n/2^k) + (2^k - 1) * c
T(1) = 1
n/2^k == 1时{p> k == logN

T(n) = 2^logN * T(1) + (2^logN - 1) * c

T(1) = 1开始并应用对数属性

T(n) = n * 1 + (n-1) * c
T(n) = n + n * c
T(n) = n * (1+c)
T(n) = O(n)

这不是O(n*logn)的线索是您不必将两个子问题组合在一起。与mergesort不同,您需要将两个子数组合并,此算法不必对递归结果执行任何操作,因此其时间可以表示为常量c

更新:背后的直觉

此算法应为O(n),因为只访问数组中的每个元素。它可能看起来并不简单,因为递归永远不会。

例如,您将问题分成两个子问题的一半大小,然后将每个子问题分成一半大小并继续进行,直到每个子问题的大小为1. 当你完成时,你将会有n个子问题,大小为1,n*O(1) = O(n)

从第一个问题开始到大小为1的N个问题的路径是对数的,因为在每个步骤中,您将细分为两个。但是在每个步骤中,您都不会对结果做任何事情,因此这不会给解决方案增加任何时间复杂性。

希望这有帮助

答案 1 :(得分:2)

最简单的方法是假设n是2的倍数,以简化:n = 2m

算法的时间复杂度是(c是常数):

t(n) = 2 t(n/2) + c

使用递归得到:

t(n) = 22 t(n/22) + 2c + c

     ...

     = 2log(n) t(n/2log(n)) + c(2log(n)-1 + ... + 22 + 21 + 20)

可以通过注意log(n) = m,从而2log(n) = 2m = n来简化。

     = n + c(2log(n)-1 + ... + 22 + 21 + 20)

最后,上面的总和可以减少到2log(n)(等于n

 t(n) = (1 + c) n

所以你的解决方案是O(n)

答案 2 :(得分:1)

您扫描列表的所有元素,即O(n)。与简单递归扫描的唯一区别 是您扫描它们的顺序。你做1,n / 2,2,3 / 4n等......而不是1,2,3 ....但复杂性是相同的。