python - 置换计算运行时复杂度有一些变化

标签 python algorithm time-complexity permutation

我对标准排列查找算法的运行时复杂性有疑问。考虑一个列表 A,查找(并打印)其元素的所有排列。

这是我的递归实现,其中 printperm() 打印每个排列:

def printperm(A, p):
    if len(A) == len(p):
        print("".join(p))
        return

    for i in range(0, len(A)):
        if A[i] != 0:
            tmp = A[i] # remember ith position
            A[i] = 0 # mark character i as used
            p.append(tmp) # select character i for this permutation
            printperm(A, p) # Solve subproblem, which is smaller because we marked a character in this subproblem as smaller
            p.pop() # done with selecting character i for this permutation
            A[i] = tmp # restore character i in preparation for selecting the next available character


printperm(['a', 'b', 'c', 'd'], [])

运行时复杂度似乎是 O(n!),其中 n 是 A 的大小。这是因为在每个递归级别,工作量减少 1。因此,顶级递归级别是 n 工作量,下一层是n-1,下一层是n-2,依此类推。所以总的复杂度是 n*(n-1)*(n-2)...=n!

现在的问题是 print("".join(p)) 语句。这行代码每次运行的时候都会遍历list,也就是遍历整个list,复杂度为n。有 n!大小为 n 的列表的排列数。所以这意味着 print("".join(p)) 语句完成的工作量是 n!*n.

print("".join(p)) 语句的存在是否会将运行时复杂度增加到 O(n * n!)?但这似乎不对,因为我没有在每次递归调用时都运行 print 语句。我获得 O(n * n!) 的逻辑在哪里崩溃了?

最佳答案

你基本上是对的!可能的混淆来自您的“......下一个级别是 n-2,依此类推”。 “等等”在递归的最底层掩盖了这一点,你不是O(1) 工作,而是 O( n) 进行打印。所以总的复杂度正比于

n * (n-1) * (n-2) ... * 2 * n

等于n! * n。请注意,.join() 对此并不重要。它也需要 O(n) 的工作来简单地 print(p)

编辑:但这并不正确,原因不同。在 print 级别之上的所有级别,您都在做

for i in range(0, len(A)):

len(A) 没有改变。所以每个 级别都在做O(n) 的工作。可以肯定的是,级别越深,A 中的零越多,因此循环所做的工作越少,但它仍然是 O(n) 只是为了迭代完全超过 range(n)

关于python - 置换计算运行时复杂度有一些变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52241264/

相关文章:

python - OpenCV 零填充

algorithm - 在 (x,y) 点的集合上生成图形

algorithm - 大 O 概念/算法逻辑,不确定我的解决方案,不太擅长循环

java - 反向然后添加序列 : Big-O runtime of my solution?

time-complexity - 什么是 O(log(n!))、O(n!) 和斯特林近似?

python - `__getattribute__` 和 `__getattr__` 中的错误处理

python - 无法从 'TypeGuard' 导入名称 'typing_extensions'

c# - 合并重叠的时间范围及其权重

python - 如何在 Python 中让一条线在屏幕上爬行?

python-3.x - 如果子字符串包含在列表中,则从字符串中删除子字符串