【问题标题】:What is the time complexity of a recursive function that spawns n - (i + 2) function calls on each iteration?在每次迭代中产生 n - (i + 2) 次函数调用的递归函数的时间复杂度是多少?
【发布时间】:2020-10-18 09:44:25
【问题描述】:

我正在研究一个名为 house robber 的 DP 问题,我已经使用 DP 方法解决了这个问题,但我最初的想法是使用以下递归函数:

def rec(self, start, possible):
        if len(possible) == 0:
            return start
        
        money = start
        for i, num in enumerate(possible):
            nextMoney = self.rec(start + num, possible[i+2:])   
            money = max(money, nextMoney)
            
        return money
            
            
    def rob(self, nums: List[int]) -> int:
        # Base Case
        if(len(nums) == 0):
            return 0
        elif len(nums) == 1:
            return nums[0]
        
        path1 = self.rec(nums[0], nums[2:])
        path2 = self.rec(nums[1], nums[3:])
        
        # Recursion
        return max(path1, path2)

我的 DP 解决方案是 O(n),但我正在努力确定上述算法的时间复杂度。我的直觉说它的指数顺序为 log(n) = O(n ^ log (n))

如果有人能在这里指出正确的方向,我将不胜感激。谢谢。

问题供参考:https://leetcode.com/problems/house-robber/

【问题讨论】:

    标签: python algorithm performance recursion


    【解决方案1】:

    代码枚举 1..n 的所有子集,没有两个相邻的数字。您对possible 进行了大量切片,这会产生每次调用的 O(n^2) 成本,因此递归关系为:

    T(n) = n^2 + sum(T(i) for i=0..n-2)
    

    从 T(n-1) 中减去 T(n):

    T(n) - T(n-1) = n^2 - (n-1)^2 + T(n-2)
    T(n) = 2n - 1 + T(n-1) + T(n-2)
    

    U(n) = T(n) + 2n + 5,所以T(n) = U(n) - 2n - 5。替换 T(n)T(n-1)T(n-2) 我们得到:

    U(n) - 2n - 5 = 2n - 1 + U(n-1) - 2(n-1) - 5 + U(n-2) - 2(n-2) - 5
    U(n) = U(n-1) + U(n-2) (simplifying)
    

    所以 U(n) = Fib(n)(即:斐波那契数),并且 T(n) = Fib(n) - 2n - 5。

    所以你的运行时是 Theta(Fib(n)),也就是 Theta(phi^n),其中 phi 是黄金分割率。

    [有趣的一点是,如果您删除了导致每次调用成本为 O(n^2) 的列表切片,那么您的代码的复杂性等级将是相同的——切片的成本会以指数形式丢失代码成本]。

    【讨论】:

    • @templatetypedef 我弄错了符号(现已修复),我在解释中添加了一个步骤。有意义吗?
    • 太好了,谢谢!我没想到会在这里看到斐波那契数字!
    • 斐波那契数自然出现是因为 {1...n} 的子集数没有两个连续数是 Fib(n+2)。
    • 哦,是的!这很有意义。我忘记了 Zeckendorf 的定理和类似的结果。我最初的预感是这会像 n!! 一样,但我忘记了我们每次调用都会显着缩小。
    猜你喜欢
    • 2020-03-13
    • 1970-01-01
    • 2015-11-29
    • 2022-11-22
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    相关资源
    最近更新 更多