时间复杂度与空间复杂性

时间:2015-11-12 06:29:49

标签: python algorithm time-complexity space-complexity

我试图从短算法中理解时间和空间复杂性之间的差异。此代码采用列表/数组并返回发生奇数次的单个数字。在Python中:

def foo(array_of_ints):
    hash_table = dict()
    for i in array_of_ints:
        hash_table[i] = hash_table.setdefault(i, 0) + 1
    for key, value in hash_table.items():
        if value%2 != 0:
            return key

有两个for循环遍历数组的长度。但是第一个循环只是在内存中创建一个哈希表/字典。时间复杂度O(n ^ 2)也是如此,因为我们两次遍历长度为n的数组,或者每个O(n)是时间复杂度和空间复杂度,因为第一个循环只是在内存中创建一个新的数据结构?

3 个答案:

答案 0 :(得分:3)

  

时间复杂度O(n ^ 2)也是如此,因为我们两次迭代一次   长度为n的数组

您的代码的时间复杂度不是O(N²)

在时间复杂度上,对长度为N的集合进行迭代被视为O(N)。原因在于,在Big-Oh表示法中,您总是对支配函数的术语感兴趣。当你达到足够大的N时,常数开始变得不那么有影响力了。

表示他们“不重要”;只有当N倾向于无穷大时,这些常数的实际效果更类似于向海洋中添加一滴水或一桶水。这种表示法旨在让您粗略(不准确)理解算法所期望的行为-i.e.随着输入大小的增加,扩展的程度如何。

这意味着您的函数可以遍历同一个集合5次,它将是O(5N),仍然是O(N)

但是你怎么得到O(N²)呢?您将开始将这些视为开始将循环嵌套在另一个内部。

示例A - O(N)

def linear(integers):
    # no nesting
    for i in integers: print(i)
    for i in integers: print(i+1)

示例B - O(N²)

def quadratic(integers):
    # notice double nesting
    for i in integers:
        for j in integers:
            print(i+j)

示例C - O(N³)

def cubed(integers):
    # notice triple-nesting
    for i in integers:
        for j in integers:
            for k in integers:
                print(i+j+k)

如果你使用矩阵,你会发现O(N³)算法的例子,至少如果你使用的是天真的实现。如果您不清楚,则称为asymptotic notation

另请注意,Big-Oh notation表示算法运行时的上限。这意味着它可以衡量它的最差案例情景。

例如,线性搜索列表中不存在的项将使您的算法达到O(N)的上限,因为它必须检查列表中的每个元素。

  

或每个时间复杂度和空间复杂度> O(n),因为第一个循环只是在内存中创建一个新的数据结构?

在这种情况下,循环所做的事情本身与测量无关。相关的是在这里占主导地位的操作,它是使循环工作的比较和增量。例如,value % 2 != 0是一个恒定时间操作¹,或O(1),并且不会对代码的运行时间做出任何实质性贡献。

  

那么空间复杂性是什么?

所需空间还取决于输入的大小和内容。算法的最坏情况是 distinct 整数数组,这意味着每个值都是唯一的。

如果每个值都是唯一的,则每个值都将导致添加键/值对。因此,该算法需要O(N)空间。

请注意,它可能会更少,但big-O表示法会传达上部绑定。

请记住,通常情况下,还需要在时间/空间限制之间进行权衡,其中更快的算法可能需要更多内存,而更多内存效率更高的替代方案可能需要更多时间。

¹这假设我们已将+-/*%等算术运算定义为 basic操作,这是常见的。

答案 1 :(得分:0)

在大O表示法中,2nn不被视为不同,因此算法具有O(n)行为。要具有O(n^2)行为,您的算法必须为数组中的每个元素遍历/构造整个数组一次。另一种说法是,你需要嵌套循环来实现O(n^2)

答案 2 :(得分:-1)

时间和空间复杂度都是O(n)。