【发布时间】:2017-12-18 23:20:03
【问题描述】:
我对@987654321@ 函数的时间复杂度有点困惑。
我在许多不同的帖子中读到,在 python 中查找数组的长度是 O(1) 和 len() 函数,其他语言类似。
这怎么可能?您是否不必遍历整个数组来计算它占用了多少索引?
【问题讨论】:
-
如果你得到答案,点击绿色勾号接受答案。
我对@987654321@ 函数的时间复杂度有点困惑。
我在许多不同的帖子中读到,在 python 中查找数组的长度是 O(1) 和 len() 函数,其他语言类似。
这怎么可能?您是否不必遍历整个数组来计算它占用了多少索引?
【问题讨论】:
您不必遍历整个数组来计算它占用了多少索引吗?
不,你没有。
在构建算法时,您通常总是可以用空间换取时间。
例如,在创建集合时,分配一个单独的变量来保存大小。然后在将项目添加到集合时增加它,并在删除某些东西时减少它。
然后,瞧,只需访问该变量即可在O(1) 时间内获得集合的大小。
这似乎是 Python 实际所做的,根据 this page,其中指出(检查 Python 源代码表明这是请求大量对象大小时的操作):
Py_SIZE(o)- 此宏用于访问 Python 对象的ob_size成员。它扩展为(((PyVarObject*)(o))->ob_size)。
如果您比较这两种方法(迭代与长度变量),可以在下表中看到每种方法的属性:
| Measurement | Iterate | Variable |
|---|---|---|
| Space needed | No extra space beyond the collection itself. | Tiny additional length (4 bytes allowing for size of about four billion). |
| Time taken | Iteration over the collection. Depends on collection size, so could be significant. |
Extraction of length, very quick. Changes to list size (addition or deletion) incur slight extra expense of updating length, but this is also tiny. |
在这种情况下,额外的成本是最低的,但为获取长度节省的时间可能相当可观,所以这可能是值得的。
情况并非总是,因为在某些(罕见的)情况下,增加的空间成本可能超过减少的时间(或者它可能需要比可用空间更多的空间)。 p>
并且,举例来说,这就是我所说的。忽略它在 Python 中完全没有必要的事实,这是一种神话般的类似 Python 的语言,它具有O(n) 的成本来查找列表的长度:
import random
class FastQueue:
""" FastQueue: demonstration of length variable usage.
"""
def __init__(self):
""" Init: Empty list and set length zero.
"""
self._content = []
self._length = 0
def push(self, item):
""" Push: Add to end, increase length.
"""
self._content.append(item)
self._length += 1
def pull(self):
""" Pull: Remove from front, decrease length, taking
care to handle empty queue.
"""
item = None
if self._length > 0:
item = self._content[0]
self._content = self._content[1:]
self._length -= 1
return item
def length(self):
""" Length: Just return stored length. Obviously this
has no advantage in Python since that's
how it already does length. This is just
an illustration of my answer.
"""
return self._length
def slow_length(self):
""" Length: A slower version for comparison.
"""
list_len = 0
for _ in self._content:
list_len += 1
return list_len
""" Test harness to ensure I haven't released buggy code :-)
"""
queue = FastQueue()
for _ in range(10):
val = random.randint(1, 50)
queue.push(val)
print(f'push {val}, length = {queue.length()}')
for _ in range(11):
print(f'pull {queue.pull()}, length = {queue.length()}')
【讨论】:
size() 方法复杂度为 O(1):链表、哈希映射等。它们都使用您描述的方法。跨度>