ArrayList
在java中是数组还是列表? get 操作的时间复杂度是多少,是 O(n)
还是 O(1)
?
Java 中的
ArrayList
是由 List
支持的 array
。
get(index)
方法是恒定时间O(1)
操作。
直接来自 Java 库的代码
ArrayList.get(index)
:
public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}
基本上,它只是直接从支持数组中返回一个值。 (
RangeCheck(index)
)也是常数时间)
它的实现是通过数组完成的,并且获取操作是O(1)。
javadoc 说:
大小、isEmpty、获取、设置、 iterator 和 listIterator 操作以常量运行 时间。加法操作在摊销常数时间内运行, 也就是说,添加n个元素需要O(n)时间。所有其他操作 以线性时间运行(粗略地说)。相比之下,常数因子较低 到 LinkedList 实现。
正如大家已经指出的那样,读取操作的时间复杂度为常数 - O(1),但写入操作有可能耗尽后备数组、重新分配和复制中的空间 - 因此运行时间为 O(n)时间,正如医生所说:
大小、isEmpty、get、set、迭代器、 和 listIterator 操作运行在 恒定时间。 添加操作运行 在摊余常数时间内,即 添加 n 个元素需要 O(n) 时间。 所有其他操作都运行在 线性时间(粗略地说)。这 与以下相比,常数因子较低 对于 LinkedList 来说 实施。
实际上,经过几次添加后,一切都是 O(1),因为每次其容量耗尽时,后备数组都会加倍。因此,如果数组从 16 开始,满了,它会被重新分配到 32,然后是 64、128,等等。所以它可以扩展,但 GC 可能会在大的重新分配期间发生。
学究气一点,它是一个由数组支持的
List
。是的,get()
的时间复杂度是 O(1)。
只是一个注释。
get(index)
方法是恒定时间,O(1)
但是如果我们知道索引就是这种情况。如果我们尝试使用
indexOf(something)
获取索引,则会花费 O(n)
数组列表基本上是数组的实现。所以对其进行 CRUD 操作的时间复杂度为:
get/read : O(1) since you can seek the address directly from base
remove/delete : O(n) why ? Because once we delete the element at index, then we need to move the after values one by one to the left.
add : O(1) becuase you always add the end of the array - next free address available.
update : O(1) since you are just changing the value but nothing value moving....across the array.
通过 ArrayList 中的索引检索元素的时间复杂度为 O(1),即常数时间。
以下是详细解释:
连续内存分配:
恒定时间访问:
类比:
补充要点:
总的来说,理解连续内存分配的概念对于掌握 ArrayList 中的高效检索操作至关重要。
注:-
当然!让我们用一个简单的例子来说明这一点。
假设我们有一个名为colors的ArrayList,包含以下元素:
colors = ["Red", "Green", "Blue", "Yellow", "Orange"]
在内存中,这些元素可能会像这样连续存储:
Memory Address | Value
---------------|------
1000 | "Red"
1004 | "Green"
1008 | "Blue"
1012 | "Yellow"
1016 | "Orange"
现在,假设我们要访问索引 2 处的元素,即“蓝色”。
为了找到“Blue”的内存位置,ArrayList 将使用一个简单的计算:
这个计算很简单,并且不依赖于ArrayList的大小。因此,在 ArrayList 中通过索引访问元素的时间复杂度是 O(1)。