当前位置: 首页 > 知识库问答 >
问题:

有没有更有效的方法来查找单链表的中间部分?(任何语言)

毋树
2023-03-14

让我们设置上下文/限制:

  1. 链表由节点对象组成

下面是我建议的解决方案的一些代码。

Node cursor = head;
Node middle = head;

while (cursor != null) {
    cursor = cursor.next;
    if (cursor != null) {
        cursor = cursor.next;
        middle = middle.next;
    }
}
return middle;

在不改变链表结构(不切换到双链表或存储长度变量)的情况下,有没有更有效的方法来查找单链表的中间元素?

注意:当此方法找到偶数个节点的中间时,它总是找到左中间。这是理想的,因为它允许您访问两者,但是如果一个更有效的方法总是能找到正确的中间,那也没关系。

共有1个答案

陆斌
2023-03-14

不,考虑到你所掌握的信息,没有比这更有效的方法了。

考虑从一个节点到下一个节点的转换。您必须执行N转换来计算列表长度。然后必须执行N/2转换以找到中间位置。

无论您是根据查找到的长度先进行全扫描,然后进行半扫描,还是并行运行光标(速度为两倍)和中间(速度为正常)指针,都与此无关,转换的总数保持不变。

使其更快的唯一方法是向您已经忽略的数据结构引入额外的信息,但是,为了完整起见,我将在这里包含它。例如:

>

  • 使其成为具有head尾部指针的双链表,因此您可以通过从两端向中间挤压在N转换中找到它。这将指针的存储需求增加了一倍,但是可能不合适。

    有一个跳过列表,每个节点都指向它的“子”和“孙子”。这将加速cursor转换,导致总共只有大约N(即每个cursor中间N/2)。像前一点一样,每个节点需要一个额外的指针。

    单独维护列表的长度,以便您可以在N/2转换中找到中间。

    与上一点相同,但在某些情况下缓存中间节点以提高速度。

    最后一点需要额外检查。像许多优化一样,您可以用空间换取时间,缓存显示了一种方法。

    首先,保持列表的长度和指向中间节点的指针。长度最初为零,中间指针最初设置为null

    如果在长度为零时要求使用中间节点,只需返回null。这是有道理的,因为列表是空的。

    否则,如果您被要求输入中间节点,而指针为null,那一定是因为您还没有缓存该值。

    在这种情况下,使用长度(N/2transitions)计算该指针,然后在返回该指针之前存储该指针以备将来使用。

    顺便说一句,当添加到列表末尾时,这里有一个特殊的情况,一些足够常见的情况需要特殊的代码。

    当长度从偶数增加到奇数时,只需将middle设置为middle即可-

    这将保存重新计算并起作用,因为您(a)有下一个指针,并且(b)您可以计算出中间“索引”(基于一个索引,并根据原始问题选择一对索引的左边)在给定长度时的变化:

    Length   Middle(one-based)
    ------   -----------------
         0      none
         1         1
         2         1
         3         2
         4         2
         5         3
         :         :
    

    这种缓存意味着,如果列表不发生变化(或者只在末尾发生变化),下次您需要中间元素时,它几乎是即时的。

    如果从列表中删除节点(或插入endpoint以外的其他位置),请将中间指针设置回null。然后在下次需要时重新计算(并重新缓存)。

    因此,对于最小的额外存储需求,您可以获得相当大的速度,特别是在需要中间元素的情况下,而不是在更改列表的情况下。

  •  类似资料:
    • 我正在开发一个java程序,它接受输入的分数,给出输入的总数和平均值,但是我很难计算出如何获得当前输入的最高分数“我使用了大量嵌套的else-if语句,但必须有一种简单的方法来实现这一点,而不是键入100个else-if语句这是我的代码。我在else-if语句开始的地方添加了一条注释,以确定最高级别

    • 问题内容: 有没有一种方法可以序列化angularjs的功能? 我的帖子现在看起来像这样。 问题答案: 这不是使用AngularJS访问表单数据的方式。表单中的数据应在范围内绑定。 因此,使用一个对象,例如$ scope.formData,它将包含您的所有数据结构,然后应使用ng-model将每个表单元素绑定到此对象。 例如: http://jsfiddle.net/rd13/AvGKj/13/

    • 问题内容: 我正在尝试弄清楚如何解析一些XML(对于Android应用程序),在Java中很难做到这一点似乎很荒谬。似乎需要创建一个具有各种回调(startElement,endElement等)的XML处理程序,然后您必须注意将所有这些数据更改为对象。类似于本教程。 我真正需要的只是将XML文档更改为多维数组,甚至更好的是拥有某种Hpricot处理器。有没有办法做到这一点,还是真的必须在上面的示

    • 我使用以下行对Sqlite查询的行进行循环。 当行数大约为15000时,需要很长时间。空的块需要大约4秒,而有一些代码的

    • 问题内容: 我的桌子上有很多记录(可能超过500 000或1 000 000)。我在此表中添加了一个新列,我需要使用该表中另一列的相应行值为该列中的每一行填充一个值。 我尝试使用单独的事务来选择每100条记录的下一个块并为其更新值,但是例如,要花费数小时来更新Oracle10中的所有记录。 在不使用某些方言特定功能的情况下,在SQL中执行此操作的最有效方法是什么,因此它可在任何地方(Oracle,

    • 问题内容: 最近,我一直在使用嵌套集模型中的废话。我喜欢为几乎所有有用的操作和视图设计查询。我坚持的一件事是如何选择节点的直接子代(并且 仅 选择子代,而不是进一步的子代!)。 老实说,我确实知道一种方法-但它涉及大量的SQL。我敢肯定有一个更直接的解决方案。 问题答案: 您是否阅读过您张贴的文章?在“查找节点的直接下属”标题下 但是,我要做的(这是作弊)是将嵌套集与邻接列表结合在一起-我在表中嵌