我要求参考这段代码:
array = [-37,-36,-19,-99,29,20,3,-7,-64,84,36,62,26,-76,55,-24,84,49,-65,41]
print sum(i for i in array if array.index(i) % 2 == 0)*array[-1] if array != [] else 0
你可以在这里看到:Python code for sum with condition
这是Quadratic,因为 for 循环后跟一个 if 语句,在括号内?
这个代码是由另一个人在同一页面上提出的 - array[-1] * sum(array[::2])
没有二次行为吗?
我认为,它又是一个二次方,因为它必须进行遍历,而且也是一个替代的遍历。
提前致谢。
答案 0 :(得分:1)
是的,array.index
使它成为二次方。
让我们先把所有不相关的东西切掉。条件是因为复杂性推理无关紧要(我们将array != []
并且该检查需要O(1)
次。与array[-1]
相乘也是如此。所以你离开了:
sum(i for i in array if array.index(i) % 2 == 0)
现在内部是一个生成器,它将扩展为一个循环遍历array
的匿名函数,并产生一堆值,每次迭代最多一次。 sum
函数接收这些值并将它们相加。
令人困惑的事情可能是发电机实际上是如何工作的。它实际上是通过运行与消费者的代码混合的生成器来工作的。这导致复杂性是生成器和消费者的复杂性的总和(即sum
)。现在sum
具有线性复杂性(它应该具有,如果我写它的话)。
因此对于生成器,它遍历数组,但是对于数组中的每个元素,它调用array.index
,其复杂度为O(N)
。
要解决此问题,您可以使用enumerate
来避免调用array.index(i)
,因为array.index(i)
返回元素的第一个索引,它可能会或可能不会是您想要执行的操作是i
,可能不是您实际找到的索引i
:
sum(i for idx, i in enumerate(array) if idx % 2 == 0)
要查看差异,请考虑列表array = [0, 1, 2, 2]
,第一个解决方案应该将此归结为4
array.index(2) == 2
,因此它还会添加第二个2
。然而,后面的解决方案将累加到2
,因为enumerate
将枚举array
中的元素,产生对(0,0)
,(1,1)
,(2,2)
, (3,2)
- 其中第一个组件是实际索引,而第二个组件是实际元素。这里省略了第二个2
,因为它实际上来自索引3
。
答案 1 :(得分:0)
第一个解决方案确实是二次方的:当你调用array.index
时,你基本上每次都会在array
上进行迭代,所以它的行为就像一个嵌入式循环。
第二个解决方案只遍历列表一次,跳过每个奇数索引。