考虑一个Arraylist。在内部它不是满的,到目前为止插入的元素数量是已知的。元素未排序。 无论ArrayList中包含的元素数量如何,选择下面列出的快速操作。 (换句话说,只需要执行几条指令)。
插入
在给定索引处插入
从指定索引获取数据
查找整数数组中的最大值(不一定排序)
在给定索引处删除
替换指定索引处的元素
搜索特定元素
我在指定的索引处选择了Insertion,从指定的索引获取数据,并替换了一个元素,但是回答键是Insertion。正如我通常所理解的那样,在ArrayList中,插入操作要求所有元素向左移动。如果我们在列表的开头做到这一点,我们将有$ O(n)$时间复杂度。但是,如果我们在最后完成它,它将是$ O(1)$。
我的问题归结为:(1)在指定索引处的插入和插入之间存在什么差异(2)如果考虑到这个特定的时间复杂度,为什么它被考虑"快速"
答案 0 :(得分:0)
对于第一个问题,答案是:
i
插入O(n)
,因为i
后的所有元素都必须向右移动一个位置。Java
(ArrayList.add())中实现的简单插入只会占用O(1)
,因为该元素会附加到数组的末尾,因此不需要移位对于第二个问题,很明显为什么简单的插入很快:不需要额外的操作,所以时间是恒定的。
答案 1 :(得分:0)
(1)在指定的索引和
处插入和插入之间存在什么差异(如果有的话)
ArrayList连续存储它的元素。添加到ArrayList的末尾不需要以任何方式更改ArrayList,除了将新元素添加到其自身的末尾。因此,该操作是O(1),当想要在数据结构中重复执行动作时采用有利的恒定时间。
但是,向索引添加元素需要ArrayList以某种方式为元素腾出空间。怎么做的?插入元素后面的每个元素都必须移动一步,以便为新插入腾出空间。您的索引是第一个元素和第n个元素之间的任何内容(包含)。因此,该操作最多为O(1),最坏的是O(n),其中n是阵列的大小。对于大型列表,O(n)比O(1)花费的时间要长得多。
(2)考虑到这种特定的插入时间复杂性,为什么它被认为是“快”
它被认为是快速的,因为它是O(1),或恒定时间。如果时间复杂度实际上只是一个操作,它尽可能快,其他小常量也被认为是快速的,并且通常由O(1)同样表示,其中“1”并不意味着严格单一操作但是,操作量不依赖于其他东西的大小,在您的示例中,它将是ArrayList的大小。然而,恒定的时间复杂度也可能涉及大的常数,但通常被认为是尽可能最快的时间复杂度。为了将其置于上下文中,O(1)操作在具有1000个元素的ArrayList中执行大约1 * k个操作,而O(n)操作需要大约1000 * k个操作,其中k是一些常量。
Big-O表示法用作度量标准,用于衡量操作或整个程序在运行时将执行的操作数。
有关大O符号的更多信息: What is a plain English explanation of "Big O" notation?
答案 2 :(得分:0)
首先看看java.util.ArrayList
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
O(1)
时间复杂度,否则需要移位所有元素,最终时间复杂度增加到O(n)
。答案 3 :(得分:0)
ArrayList内部只是一个数组本身,它使用Array.copyOf
创建一个增加大小的新数组,但是原始内容完好无损。
所以关于插入,无论你做一个简单的添加(将在数组的末尾添加数据)还是在第一个(第0个)索引上,它仍然会比大多数数据结构更快,同时要记住简单性数据结构。
唯一的区别是简单的add不需要遍历,但是在索引处添加需要将元素向左移动,类似于删除。这使用System.arrayCopy
将一个数组复制到另一个数组,并改变了索引和数据。
所以,是的简单插入比索引插入更快。