复杂性分析和递归关系

Posted

技术标签:

【中文标题】复杂性分析和递归关系【英文标题】:Complexity analyisis & recurrence relations 【发布时间】:2017-12-02 15:34:06 【问题描述】:

我正在尝试查找以下两个递归函数的复杂性,但不知道如何对递归函数进行复杂性分析

找到所有可能的子集

def subsetsHelper(self, nums, index, path, res):
    if path is None:
        return
    res.add(path)
    for i in range(index, len(nums)):
        self.subsetsHelper(nums, i + 1, path + [nums[i]], res)

def subsetsWithDup(self, nums):
    res = []
    self.subsetsHelper(nums, 0, [], res)
    return res

找到所有可能的排列

def permuteHelper(self, nums, index, path, res):
    if len(nums) == 0:
        res.append(path)

    for i in range(len(nums)):
        copy = list(nums)
        val = copy.pop(i)
        self.permuteHelper(copy, i, [val] + path, res)

def permute(self, nums):
    res = []
    self.permuteHelper(nums, 0,[], res)
    return res

还有,函数的递推关系是什么

【问题讨论】:

【参考方案1】:

如果nums的长度为n,则第一种算法的时间复杂度关系为T(n) = T(n-1) + T(n-2) + ... + T(1) + 1。现在尝试通过展开方程来解决这个问题。

T(n) = T(n-1) + T(n-2) + ... + T(1) + 1
T(n) = (T(n-2) + T(n-3) + ... + T(1) + 1) + T(n-2) + ... + T(1) + 1 
T(n) = 2T(n-2) + 2T(n-3) + ... + 2T(1) + 2
T(n) = 2(T(n-3) + T(n-4) + ... + T(1) + 1) + 2T(n-3)... + 2T(1) + 2  
T(n) = 2^2 T(n-3) + 2^2 T(n-4) + ... + 2^2T(1) + 2^2

因此,T(n) = O(2^n)

正如评论中提到的,对于第二种算法,您在每次迭代中都有一个副本,并调用除一个之外的相同数组的函数。因此,T(n) = n * T(n-1) + n^2n^2 是数组的n 副本,大小为n)。使用扩展,我们将有:

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

因此T(n) = O((n + 1)!)

【讨论】:

在第一个算法中,在该循环的每次迭代中,我们递增i,因此下一次递归调用中的迭代每次减少1。但是在该循环的每次迭代中的第二种算法中,长度保持不变。所以我应该像T(n) = n*T(n-1) + O(n^2)这样重复出现O(n!)(不确定这种重复出现的解决方案)。

以上是关于复杂性分析和递归关系的主要内容,如果未能解决你的问题,请参考以下文章

递归算法的时间复杂度分析

掌握递归关系时间复杂度的定理

如何为给定的代码编写递归关系

算法 入门

给定递归算法解决递归关系并给出最坏情况下的时间复杂度,这是正确的吗?

《算法设计与分析》期末不挂科