简体   繁体   English

两个链表的交集

[英]Intersection of two linked lists

给定两个排序的链表L1和L2,这是计算它们的交点L1交点L2的解决方案。

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

(Translate to C yourself.) (自己翻译成C。)

Since they are singly linked lists if the two linked lists intersect they would form a Y shape with one arm longer or equal to the other. 由于它们是单链表,如果两个链表相交,则它们将形成Y形,一只手臂的长度大于另一只手臂。 Let l1 be the length of L1 list and l2 be the length of L2 list. 令l1为L1列表的长度,l2为L2列表的长度。

Suppose that l1 > l2. 假设l1> l2。 Start matching the pointers of List L1 from point (l1-l2) and list L2 from its beginning where ever they point to the same node that node will be the matching point. 从点(l1-l2)开始匹配列表L1的指针,从列表L2的起点开始匹配列表L2的指针,无论它们指向哪个节点,该节点将成为匹配点。

If l2 is greater than l1 then do the other way. 如果l2大于l1,则执行另一种方法。

How about the solution below, it is O(n+m) and takes a dummy node which is pointing to the Head node. 下面的解决方案怎么样,它是O(n + m)并采用一个指向Head节点的虚拟节点。 The Head node is a class level variable here, so even if L1 is pointing to the current, Head always has the full list. Head节点在此处是类级别的变量,因此,即使L1指向当前节点,Head始终具有完整列表。

I have compiled and tested, runs fine for simple inputs like L1: 1->5>6>7>8>10 and L2:2>4>6>8 , output is 6>8 我已经编译并测试过,对于像L1的简单输入可以正常运行:1-> 5> 6> 7> 8> 10和L2:2> 4> 6> 8,输出是6> 8

Any ideas about how to go with unsorted lists? 关于如何处理未排序列表的任何想法? I couldnt think of a O(n) solution 我想不出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;


  }

The basic approach to in-order merge-like algorithms is that you never need to consider more than three items at a time - the front items from each input list, plus potentially a saved result. 有序合并式算法的基本方法是您一次不必考虑三个以上的项目-每个输入列表中的最前面的项目以及可能保存的结果。

In this case, I'd use... 在这种情况下,我会使用...

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

Now the nasty - this loop assumes the lists are infinite. 现在很讨厌-这个循环假设列表是无限的。 How do you handle empty lists? 您如何处理空列表? That's fiddly, unless you can reserve a sentinel value which is greater than any legal value that can occur in the list. 这很奇怪,除非您保留的哨兵值大于列表中可能出现的任何合法值。

If you can't reserve a sentinel, you can fake the effect - write a compare function that checks whether there's a next item in each queue before comparing values, and treats "queue exhausted" as implying the sentinel value. 如果您无法保留前哨,则可以伪造该效果-编写一个比较函数,在比较值之前检查每个队列中是否存在下一个项目,并将“队列耗尽”视为隐含前哨值。

That gives... 那给...

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 面向对象

This is a union. 这是一个工会。 Converting to an intersection is left as an exercise for the reader. 读者可以将转换为交集作为练习。

EDIT 编辑

OK - it is now an intersection. 好的-现在是十字路口。 Just discarding the less-than items rather than adding them to the output. 只是丢弃小于项目,而不是将其添加到输出中。 Also fixed a typo. 还修正了错字。

Note - my interpretation was that the output of an intersection should be a set, meaning no duplicates. 注意-我的解释是,相交的输出应该是集合,这意味着没有重复。 This tolerates duplicates in the inputs, but the output is duplicate-free. 这样可以容忍输入中的重复项,但是输出是无重复项的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM