Python 3.x 此功率集功能的时间和空间复杂性是什么?
你好,我一直在练习算法和数据结构,我解决了哪个是powerset函数,但我的解决方案似乎太慢了。 代码如下:Python 3.x 此功率集功能的时间和空间复杂性是什么?,python-3.x,recursion,time-complexity,space-complexity,powerset,Python 3.x,Recursion,Time Complexity,Space Complexity,Powerset,你好,我一直在练习算法和数据结构,我解决了哪个是powerset函数,但我的解决方案似乎太慢了。 代码如下: def subsets(array): set = [array] n = len(array) for i in range(n): tmp_subsets = subsets(array[:i] + array[i+1:]) for subset in tmp_subsets: if subset not
def subsets(array):
set = [array]
n = len(array)
for i in range(n):
tmp_subsets = subsets(array[:i] + array[i+1:])
for subset in tmp_subsets:
if subset not in set:
set.append(subset)
return set
我知道还有其他更好/更快的解决方案,但我正在努力了解这一解决方案的时间和空间复杂性
我认为这里的时间复杂度是O(n^n)
,因为递归树每个级别有n
个分支和n
个总级别,对吗
因此,它比最优的O(2^n)
解更差
虽然我不确定空间的复杂性,但我的直觉是O(2^n)
,但当我画递归树时,它有点混乱,因为我在递归堆栈最大的位置使用的空间是:
space_for_level(0)+space_for_level(1)+...+space_for_level(n)
n + (n-1) +...+ 1 = O(n^2)
但是最后当我返回所有内容时,set
的大小是O(2^n)
所以我的空间复杂度是O(2^n+n^2)=O(2^n)
我的分析在时间和空间上都正确吗?欢迎任何帮助我以更清晰的方式思考的建议。时间复杂性 时间复杂度可归纳为以下递推关系:
T(n)=n*T(n-1)+n*2^(n-1)
因为有一个主循环运行了n次,每次剩余元素的子集(n-1
)都首先生成(T(n-1)
),然后循环(2^(n-1)
)
注意该关系假设循环中的每一个其他操作都需要恒定的时间,这是一个合理的近似值,因为它在n
增长时的影响最小。例如,此操作:
if subset not in set
不需要固定时间(它需要列表长度中的线性时间,也就是集合。append(subset)
通常不是固定时间),但是现在让我们忽略它(您可以了解图片以及如何分析代码)
递归关系表明复杂性至少是指数级的
空间复杂性
首先,生成n
的所有子集,这意味着至少复杂性为O(2^n)
。然而,由于在每个步骤中递归和重新生成子集,空间复杂度比这还要高。具体而言,在每个循环步骤中,生成n-1
子集的一个运行副本,然后将其扩充到原始子集。我们有:
S(n)=S(n-1)+2^n
由于对子集的每次调用都会生成1
剩余子集的中间运行副本(即S(n-1)
)再加上它将这些子集组合成2^n
的原始子集
<强>注我们不计算存储子集集的每个项所需的存储量,这本身需要在O(n)< /C>中存储复杂度,但考虑到这是为了简单地存储< <代码> o(1)< /C> >为简单起见(例如,在二进制编码中,将子集存储为一个字,对于较小的n,它在时间和空间上是指数的。需要应用指数性能的确切形式,但在这种情况下,递归是T(n)=nT(n-1)
这个定理并不适用……非常感谢你的见解。我认为你对时间复杂性的分析非常准确而且非常有用。但是,当谈到空间复杂性时,我有点困惑。你是说S(n)=S(n-1)+2^n
其中2^n
对应于set
和S(n-1)
对应于tmp_子集
。如果是这样,我们就不能说s(n-1)=s(n-2)+2^(n-1)…s(1)=s(0)+2
-->s(n)=O(2^n)
。另一种方法是查看递归树,找出程序何时使用了最多的空间,这在我们开始回溯和set
开始接近'2^n'之前不会发生,因此我们使用最多内存的时间是我们最后一次对tmp\u子集中的子集执行操作时:
意思是set
和tmp\u子集
都是O(2^n)
-->S(n)=O(2^n)
。让我知道你的想法。[1,…,n]
的所有子集不是都占用O(n2^(n-1))空间吗?@d\darric,空间复杂性如前所述,因为代码使用了S(n-1)的临时存储
生成临时n-1
子集加上返回所有当前子集所需的2^n
存储。可以尝试说S(n-1)
只是2^(n-1)
,但事实并非如此,因为它递归地需要更多空间来生成临时S(n-2)
子集等等..在任何情况下,人们都可以求解递归关系并获得复杂度的精确形式,我认为(不求解它)是O(n2^n)
order.@NikosM。这可能不是您的意图,但请不要像我们通常那样建议人们进行交叉张贴。建议另一个站点进行重新制定或后续问题当然可以,只要这不会导致不必要的交叉站点重复。谢谢!