【问题标题】:Linked List getValue(int n) should be O(n / 2) [closed]链表 getValue(int n) 应该是 O(n / 2) [关闭]
【发布时间】:2014-05-07 11:27:20
【问题描述】:

标准的链表实现是双向链接的。因此我们分别有一个headNode和一个tailNode。我已经阅读了 getValue(int n),作为返回保存在列表中第 n 个元素的数据部分。现在假设我们从 headNode 开始对链表进行顺序搜索,如果位置是链表中的最后一个元素,最坏的情况将是 O(n)。但是,如果我们检查是否 n > size / 2,那么我们就知道是在 headNode 还是在 tailNode 开始遍历。这意味着它将执行 O(n / 2),可以重写为 O(1/2n)。

根据 Big O Notation 的规则,系数无关紧要,因此最坏的情况仍然是 O(n)。我看到了这个逻辑的一个缺陷,因为如果我们有一个包含大量节点的列表,比如 100 万个,那么最坏的情况是 500,000 比最坏的情况 1,000,000 好得多。最坏的情况是如果我们正在搜索的位置实际上是 size / 2。我已经实现了这段代码,发现当通过的位置小于 size / 2 时,它们以相同的速度执行,但是,当通过的位置大于 size / 2,它的执行速度明显更快。我的问题是,当这样一个简单的解决方案将最坏的情况减半时,我们怎么能说这是 O(n)。显然,系数很重要,我看不出我们如何得出它们无关紧要的结论。代码如下:

//This is headed by firstNode and tailed by lastNode
public Node getValue(int position)
{
    if (!isEmpty() && position <= size)
    {

        if (position > (size / 2))
            return traverseReverse(position);
        else
            return sequentialSearch(position);

    }

    return null;
}

private Node traverseReverse(int searchIndex)
{
    Node currentNode = lastNode;
    int position = size;
    while (currentNode != null)
    {
        if (position == searchIndex)
            return currentNode;

        position--;
        currentNode = currentNode.previous;
    }

    return null;
}

private Node sequentialSearch(int position)
{
    Node currentNode = firstNode;
    int n = 0;

    while (currentNode != null)
    {
        if (n == position)
            return currentNode;

        n++;
        currentNode = currentNode.next;
    }

    return null;
}

【问题讨论】:

  • 这个问题似乎是题外话,因为它是关于计算机科学中的通用概念而不是编程。考虑在Computer Science.SE 上问这个问题
  • 复杂性不等于性能。它描述了算法的渐近行为,这意味着随着 N 的增加,它将如何表现,这在这里显然是线性的。
  • 无论如何请记住,O 表示法用于表示渐近复杂性。这意味着您应该只考虑 big n。以n = 10^50 为例,在这样的列表中搜索一个元素需要数十亿年的时间。以n = 10^50/2 为例,它仍然需要数十亿年的时间来搜索元素,从实际的角度来看并没有真正改变。然而,在10^50 元素向量中进行二等分搜索,现在大约需要50 * log2(10) 操作才能找到元素,这是瞬时就是大哦想要处理的事情。
  • 是的,这个问题听起来像是个误会。对于非常大的 n,执行时间与 N 成正比增长。例如,与 O(nn) 相比,O(n) 非常接近 O(n/2)。与 O(nn/2) 相比,O(n/2) 也是如此。由于我们正在研究运行时根据 N 扩展的方式,因此常数因子确实足够小,以至于在比较此类术语时,您可以忽略较大的 n。
  • 另一种看待大 O 的方式是,您可以对 O(N) 算法进行所有您想要的性能改进,但只要生成的算法仍然是 O(N),它'对于足够高的 N 值,它仍然比任何 O(log N) 算法都要慢。这几乎是算法中大 O 的实际目的。

标签: java performance algorithm doubly-linked-list


【解决方案1】:

复杂性和运行时是相关的概念,但并不完全相同。复杂性显示n 与运行时之间的关系,随着n 的增加。

无论系数如何,线性关系都是 O(n)。如果您想比较最坏情况的运行时间,请务必这样做,但复杂性分析不是正确的工具。这只是一个起点。

无论您从前面还是后面搜索链接列表,您需要查看的平均项目数与其大小成正比。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 2019-12-13
    • 2012-11-22
    • 1970-01-01
    相关资源
    最近更新 更多