【问题标题】:Why is accessing any single element in an array done in constant time ( O(1) )?为什么要在恒定时间( O(1) )内访问数组中的任何单个元素?
【发布时间】:2014-05-30 23:40:27
【问题描述】:

根据Wikipedia,访问数组中的任何单个元素都需要恒定的时间,因为只需执行一次操作即可找到它。

在我看来,幕后发生的事情大概是这样的:

a) 搜索是线性完成的(例如,我想访问元素 5。我从索引 0 开始搜索,如果它不等于 5,我转到索引 1 等) 这是 O(n) - 其中 n 是数组的长度

b) 如果数组存储为 B-tree,这将给出 O(log n)

我没有看到其他方法。

有人能解释一下为什么以及如何在 O(1) 中完成吗?

【问题讨论】:

  • 可以根据索引计算元素的偏移量。该计算具有恒定的时间,例如size_of_an_element * (index - 1)
  • 元素 5 位于索引 5。这就是“索引”应用于数组时的含义。您不必扫描索引 0 到 4。

标签: arrays algorithm time-complexity


【解决方案1】:

数组从特定的内存地址start 开始。每个元素占用相同数量的字节element_size。数组元素从起始地址开始依次位于内存中。所以你可以用start + i * element_size计算元素i的内存地址。此计算与数组大小无关,因此为O(1)

【讨论】:

  • 但是这个涉及乘法和加法运算的内存地址的计算本身会随着n而缩放,对吗?因此它不是真正的O(1)
  • @pikachuchameleon 严格来说你是对的。但是对于具有大小为k(例如32 或64 位)的固定宽度寄存器的实际计算机系统,n 通常可以用k 位(n<2^k)表示。所以在这种情况下,乘法和加法是在恒定时间内完成的。
【解决方案2】:

理论上,数组的元素具有相同的已知大小,并且它们位于内存的连续部分中,因此如果数组的开头位于 A 内存地址,如果您想访问任何元素,您必须计算它的地址是这样的:

A + item_size*index 所以这是一个常数时间操作。

【讨论】:

    【解决方案3】:

    访问单个元素不会找到值为x的元素。

    访问元素i意味着获取数组第i个位置的元素。

    这是在O(1) 中完成的,因为它非常简单(恒定数量的数学计算)给定索引、数组的开头和每个元素的大小。

    RAM 内存为访问 RAM 中的每个地址提供了一个恒定的时间(或者更准确地说,一个有界的时间),并且由于找到地址是 O(1),并且检索其中的元素也是 O(1 ),它给你总共O(1)

    查找值为x 的元素是否实际上是Omega(n) 问题,除非有更多关于数组的信息(例如排序)。

    【讨论】:

    • 它是大 O,不是大Ω ;-)
    • @rubenvb 不,它是Omega(n) - 这是一个无法比c*n 做得更好的问题(对于某些常量c),与'排序是Omega(nlogn) 问题相同。任何找到元素的解决方案都是Omega(n)。我们可以想到(效率极低的)解决方案,而不是O(n)
    【解决方案4】:

    通常,数组被组织为一个连续的内存块,其中每个位置都可以通过索引计算来访问。对于任意大小的数组,这种索引计算不能在恒定时间内完成,但由于可寻址空间的原因,所涉及的数字受机器字大小的限制,因此假设恒定时间是合理的。

    【讨论】:

    • This index calculation cannot be done in constant time for arrays of arbitrary size -> 这是什么意思?
    • 我的意思是,在每台实际的计算机(或者说计算环境)中,可寻址空间都有一个上限。在 80 年代,通常 64k 或 128k(通过内存扩展和银行切换)是典型的,后来(较旧的 Windows 机器)是 4gb。今天,可通过 64 位寻址的内存空间很常见。简而言之:实际可寻址空间通常受架构相关常数的限制,因此索引计算的时间也受常数限制。一些计算模型会考虑到这一点,而另一些则不会。
    【解决方案5】:

    如果你有 Int 数组。每个 int 在 java 中都是 32 位的。例如,如果您在 java 中有 10 个整数,则意味着您分配了 320 位的内存。然后电脑就知道了

    0 - 索引在内存中,例如 - 39200

    最后一个索引位于内存 39200 + 数组的总内存 = 39200+320= 39520

    那么如果你想访问索引 3。那么它是 39200 + 32*3 = 39296。

    这完全取决于您存储在数组中的对象占用多少内存。请记住数组占用整个内存块。

    【讨论】:

    • 最后一个元素的索引将是 39200 + 9 * 32 + 1 = 39 489。通常,如果你想访问n`th元素值,计算机将从array_offset_in_memory + (n - 1) * size_of_type_of_array + 1开始读取size_of_type_of_array位.
    猜你喜欢
    • 1970-01-01
    • 2019-01-19
    • 2011-11-10
    • 2017-08-13
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 2016-09-17
    • 1970-01-01
    相关资源
    最近更新 更多