两个链表的交集

时间:2010-01-31 11:14:58

标签: c algorithm data-structures

给定两个已排序的链接列表,L1和L2,一个计算它们的解决方案 交叉点 L1交叉点L2

4 个答案:

答案 0 :(得分:10)

L1_node = L1.head;
L2_node = L2.head;
Result = new SList;
while L1_node != NULL and L2_node != NULL:
  if L1_node.value == L2_node.value:
     Result.append(L1_node.value)
     L1_node = L1_node.next
     L2_node = L2_node.next
  elif L1_node.value < L2_node.value:
     L1_node = L1_node.next
  else
     L2_node = L2_node.next

(自己翻译成C语言。)

答案 1 :(得分:1)

由于它们是单链表,如果两个链表相交,它们将形成Y形,其中一条臂长或等于另一条。设l1为L1列表的长度,l2为L2列表的长度。

假设l1> L2。 从点(l1-l2)开始匹配List L1的指针,并从它们的开头列出L2,它们指向节点将成为匹配点的同一节点。

如果l2大于l1,则采用另一种方式。

答案 2 :(得分:0)

下面的解决方案如何,它是O(n + m)并且采用指向Head节点的虚节点。 Head节点在这里是一个类级变量,所以即使L1指向当前,Head也总是有完整的列表。

我已经编译和测试,对于像L1这样的简单输入运行良好:1-> 5> 6> 7> 8> 10和L2:2> 4> 6> 8,输出为6> 8

有关如何使用未排序列表的任何想法?我想不出O(n)解决方案

public Node ReturnIntersection(Node Head, Node L2) { if ((Head == null) || (L2 == null)) return null;

     Node temp = null;
      Node L1 = Head;


      while (L1.next != null && L2.next != null)
      {
          if (L1.data == L2.data)
          {
              L1 = L1.next;
              L2 = L2.next;
          }

          else if (L1.data < L2.data)
          {
              temp = L1.next;
              L1.data = temp.data;
              L1.next = temp.next;

          }

          else if (L1.data > L2.data)
          {
              L2 = L2.next;

          }

      }

      if (L1 != null)
      {
          while (L1.next != null)
          {
              L1.next = null;

          }
      }
      return Head;


  }

答案 3 :(得分:-1)

有序合并算法的基本方法是,您一次不需要考虑三个以上的项目 - 每个输入列表中的前面项目,以及可能保存的结果。

在这种情况下,我会使用......

loop forever
  while in1.value < in2.value : transfer item from in1 to output
  while in2.value < in1.value : transfer item from in2 to output

  if in1.value == in2.value :
    transfer item from in1 to output
    discard item from in2

    while in1.value == value just transferred : disard item from in1
    while in2.value == value just transferred : disard item from in2

现在令人讨厌 - 这个循环假定列表是无限的。你如何处理空表?这很麻烦,除非你能保留一个sentinel value,它大于列表中可能出现的任何合法价值。

如果你不能保留一个哨兵,你可以伪造效果 - 写一个比较函数,在比较值之前检查每个队列中是否有下一个项目,并将“队列耗尽”视为暗示哨兵值。

这给了......

loop forever
  while in1.value < in2.value : discard item from in1
  while in2.value < in1.value : discard item from in2

  if in1 exhausted, break out of loop
  if in2 exhausted, break out of loop

  if in1.value == in2.value :
    transfer item from in1 to output
    discard item from in2

    while in1.value == value just transferred : discard item from in1
    while in2.value == value just transferred : discard item from in2

<强> OOPS

这是一个联盟。转换为十字路口是留给读者的练习。

修改

好的 - 它现在是一个十字路口。只丢弃少于项目而不是将它们添加到输出中。还修了一个错字。

注意 - 我的解释是交集的输出应该是一个集合,意味着没有重复。这容许输入中的重复,但输出是无副本的。