了解如何衡量函数的时间复杂度

时间:2018-01-09 04:08:34

标签: python performance big-o

这是功能:

c = []
def badsort(l):
  v = 0
  m = len(l)
  while v<m:
    c.append(min(l))
    l.remove(min(l))
    v+=1
  return c

虽然我意识到这是一种非常低效的排序方式,但我想知道这样一个函数的时间复杂度是多少,因为虽然它没有嵌套循环,但它会多次重复循环。

3 个答案:

答案 0 :(得分:4)

以下是一些有用的信息,可帮助您了解如何找到函数的复杂性。

  1. 测量迭代次数
  2. 衡量每次迭代时每项操作的复杂性
  3. 对于第一点,您会看到终止条件为v < m,其中v最初为0,m是列表的大小。由于v在每次迭代时递增1,因此循环最多运行(至少)N次,其中N是列表的大小。

    现在,第二点。每次迭代我们都有 -

    c.append(min(l))
    

    其中min是线性操作,花费O(N)时间。 append是一个持续的操作。

    接下来,

    l.remove(min(l))
    

    同样,min是线性的,remove也是如此。因此,您有O(N) + O(N),即O(N)

    总之,您需要O(N)次迭代,每次迭代O(N),使其成为O(N ** 2)或二次。

答案 1 :(得分:4)

术语

假设n = len(l)

迭代次数

外环运行n次。内循环中的min()比l(这里的优化空间)运行两次,但是对于递增递减的数字(对于循环的每次迭代,l的长度减少,因为每次从列表中删除一个项目)。

这种复杂性为2 * (n + (n-1) + (n-2) + ... + (n-n))。 这等于2 * (n^2 - (1 + 2 + 3 + ... + n))。 括号中的第二项是triangular number,并且分为n*(n+1)/2

因此,您的复杂性等于2*(n^2 - n*(n+1)/2))。 这可以扩展到2*(n^2 - n^2/2 - n/2), 并简化为n^2 - n

BigO表示法

BigO表示法对整体增长趋势感兴趣,而不是函数的精确增长率。

Drop Constants

在BigO表示法中,常量被删除。由于没有常数,因此我们仍然使用n^2 - n

仅保留主导条款

此外,在BigO表示法中,只考虑主导术语。 <{1}}占据n^2的主导地位,因此n被删除。

结果

这意味着BigO中的答案是n,即二次复杂度。

答案 2 :(得分:3)

此问题的时间复杂度为O(n^2)。虽然代码本身只有一个明显的循环,while循环,minmax函数都是O(n)实现,因为在最坏的情况下,它必须扫描整个列表以查找相应的最小值或最大值。 list.removeO(n)因为它必须遍历列表,直到它找到第一个目标值,在最坏的情况下,它可能在最后。由于方法的巧妙实施,list.append摊销 O(1),因为list.append技术上O(n)/n = O(1)推送n个对象:

def badsort(l):
  v = 0
  m = len(l)
  while v<m: #O(n)
    c.append(min(l)) #O(n) + O(1) 
    l.remove(min(l)) #O(n) + O(n)
    v+=1
  return c

因此,有:

Outer(O(n)) * Inner(O(n)+O(n)+O(n)) = Outer(O(n)) * Inner(O(n))

O(n)+O(n)+O(n)可以合并为O(n),因为大o会衡量最坏情况。因此,通过组合外部和内部的复杂性,最终的复杂性是O(n^2)