【问题标题】:Time Complexity of finding the length of an array查找数组长度的时间复杂度
【发布时间】:2017-12-18 23:20:03
【问题描述】:

我对@9​​87654321@ 函数的时间复杂度有点困惑。

我在许多不同的帖子中读到,在 python 中查找数组的长度是 O(1) 和 len() 函数,其他语言类似。

这怎么可能?您是否不必遍历整个数组来计算它占用了多少索引?

【问题讨论】:

  • 如果你得到答案,点击绿色勾号接受答案。

标签: arrays time-complexity


【解决方案1】:

您不必遍历整个数组来计算它占用了多少索引吗?

不,你没有。

在构建算法时,您通常总是可以用空间换取时间。

例如,在创建集合时,分配一个单独的变量来保存大小。然后在将项目添加到集合时增加它,并在删除某些东西时减少它。

然后,瞧,只需访问该变量即可在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()}')

【讨论】:

  • 我很确定所有 Java 容器的 size() 方法复杂度为 O(1):链表、哈希映射等。它们都使用您描述的方法。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-02
  • 2012-11-27
  • 1970-01-01
  • 1970-01-01
  • 2013-04-01
相关资源
最近更新 更多