【问题标题】:Time complexity in JavaJava中的时间复杂度
【发布时间】:2012-03-04 10:27:35
【问题描述】:

对于 ArrayList Java API 的方法 add 声明:

添加操作运行在摊销的常数时间内,即添加n个元素需要O(n)时间。

我想知道当使用 LinkedList 的 add 方法时,它是否是相同的时间复杂度,线性的。

【问题讨论】:

标签: java arraylist linked-list time-complexity


【解决方案1】:

这取决于您要添加的位置。例如。如果在 ArrayList 中添加到列表的前面,则实现每次都必须移动所有项目,因此添加 n 个元素将在二次时间内运行。

与链表类似,JDK 中的实现保持一个指向头部和尾部的指针。如果你一直追加到尾部,或者追加到头部的前面,那么操作将在线性时间内运行 n 个元素。如果你在不同的地方追加,实现将不得不在链表中搜索正确的地方,这可能会给你带来更糟糕的运行时间。同样,这取决于插入位置;如果您在列表的中间插入,您将获得最差的时间复杂度,因为必须遍历最大数量的元素才能找到插入点。

实际的复杂性取决于您的插入位置是恒定的(例如始终在第 10 位),还是列表中项目数的函数(或对其进行任意搜索)。第一个会给你 O(n) 一个稍差的常数因子,后者 O(n^2)。

【讨论】:

  • 好的,这是有道理的。我要添加到列表的前面,因此 ArrayList 将是二次的,而链表是线性的
  • 是的,但添加到前面最好使用ArrayDeque,这将非常适合此任务。几乎总有比LinkedList 更好的结构:)
  • @BrianRoach 向 ArrayList 的头部添加一个元素不是 O(1),而是 Martins 所说的 O(n)。
【解决方案2】:

在大多数情况下,ArrayListadd() 方法上的性能优于 LinkedList,因为它只是保存指向数组的指针并递增计数器。

但是,如果工作数组不够大,ArrayList 会增大工作数组,分配一个新数组并复制内容。这比向LinkedList 添加新元素要慢——但如果你不断添加元素,那只会发生 O(log(N)) 次。

当我们谈论“摊销”复杂性时,我们会采用为某个参考任务计算的平均时间。

所以,回答你的问题,它的复杂性不一样:在大多数情况下它要快得多(尽管仍然是 O(1)),有时要慢得多(O(N))。最好使用分析器检查什么对您更好。

【讨论】:

    【解决方案3】:

    如果你指的是add(E)方法(不是add(int, E)方法),答案是肯定的,将单个元素添加到LinkedList的时间复杂度是恒定的(添加n个元素需要O(n)时间)

    作为Martin Probst indicates,不同的位置你得到不同的复杂性,但add(E) 操作将始终将元素附加到尾部,从而导致恒定(摊销)时间操作

    【讨论】:

    • add(E) 操作将始终将元素附加到尾部,从而导致恒定时间操作 - 不完全正确,对于ArrayList,它很可能是 O(N)。
    • @alf 没错,当ArrayList 达到它的限制并且必须重新生成时。我添加了一个声明,它以恒定(摊销)时间运行
    猜你喜欢
    • 1970-01-01
    • 2016-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 2011-09-26
    • 1970-01-01
    • 2021-05-29
    相关资源
    最近更新 更多