链接列表问题

时间:2010-09-18 04:29:09

标签: c algorithm linked-list

Hiii ......

如果我们给出了两个链表(可能长度不同),那么从末端开始的几个节点是常见的...我们如何在最短的时间内找到第一个公共节点......?

这些名单是单独链接的。一些节点从最后是常见的,我们需要从它们中找到第一个共同的节点。

3 个答案:

答案 0 :(得分:5)

  • 统计两个列表 - O(n)
  • 省略较长列表中列表长度之间的差异
  • 在列表上同时迭代,直到找到一个公共节点 - O(n)

总复杂性: O(n)

例如:

1→2→3→4-&将7-> 8
--------- 5→6-&将7-> 8

我们希望得到 7 ,因为它是第一个公共节点。

  1. 计算清单 - 第一个= 6,第二个= 4.
  2. 在第一个(更长)列表中跳过两个(6-4 = 2)个元素。
  3. 同时迭代 3.1。 3 == 5是假的 3.2。 4 == 6是假的 3.3。 7 == 7为真,则7为公共节点

答案 1 :(得分:1)

假设每个链表都有一个完全唯一的集合,我看到的唯一方法是使用嵌套的for循环,效率非常低。如果数据集不是唯一的,您可以使用第三个(链接的)列表作为唯一节点的缓存,但仍然在查看最坏情况下的O(n²)

答案 2 :(得分:1)

O(n)解决方案,用于查找其中一个列表中具有相同值的第一个节点。然后,您可以从该节点中提取值。

除非另有说明,否则所有代码部分(注释)都是O(1),并且没有嵌套的O(n)操作。因此整个解决方案是O(n)。

它的工作原理是计算每个列表中的元素,然后推进最长列表的指针,以便结束对齐。

然后以同步方式逐步浏览两个列表。如果节点匹配且先前未匹配,则会保存该节点(,只要它们匹配,因为您希望序列中的最早匹配)。

如果它们不匹配,则保存该事实,以便后续匹配将被视为序列中最早的匹配。

当你到达两个列表的末尾时,你要么指出没有匹配(如果两个列表的最后一个节点不同),要么是序列中最早的匹配。

当然只有伪代码,因为它是作业:

def findCommonNode (head1, head2):

    # Work out sizes O(n)

    set count1 and count2 to 0

    set ptr1 to head1
    while ptr1 is not equal to NULL:
        increment count1
        set ptr1 to ptr1->next

    set ptr2 to head2
    while ptr2 is not equal to NULL:
        increment count2
        set ptr2 to ptr2->next

    # If either size is 0, no match possible.

    if count1 == 0 or count2 = 0:
        return NULL

    # Make the first list longer (or same size).

    if count1 < count2:
        swap count1 and count2
        swap head1 and head2 (local copies only)

    # Move through longest list until they're aligned O(n).

    set ptr1 to head1
    set ptr2 to head2

    while count1 is greater than count2:
        decrement count1
        set ptr1 to ptr1->next

    # Initially mark as non-match.

    set retptr to NULL

    # Process both (aligned) lists O(n).

    while ptr1 is not equal to NULL:
        # If equal and if first match after non-match, save position.

        if ptr1->data is equal to  ptr2.data:
            if retptr is equal to NULL:
                set retptr to ptr1
        else:
            # If not equal, mark as non-match.

            set retptr to NULL

        # Advance to next element in both lists.

        set ptr1 to ptr1->next
        set ptr2 to ptr2->next

    # Return the earliest match.

    return retptr

假设您有两个列表1,2,3,4,5,5,6,7,8,90,6,9,8,9。根据大小差异对齐这些并推进列表1指针,您将得到:

          v
1 2 3 4 5 5 6 7 8 9
          0 6 9 8 9
          ^

然后将match设置为NULL并开始处理。它们不匹配(5/0),因此您将第一个匹配节点设置为NULL(即使它已经为NULL)并前进到6/6

这些(6/6)匹配(并且当前匹配为NULL),因此您将其中一个的地址保存为匹配,然后前进。

7/9不匹配,因此您再次将匹配设置为NULL,然后前进。

8/8匹配且匹配为NULL,因此您再次将匹配设置为其中一个,然后前进。

9/9也匹配,但匹配已设置,因此您不会更改它。然后推进两个列表中的元素。

然后返回匹配为8个节点之一。这是你最常见的尾随部分。