判断两个单链表是否相交--java实现

题目描述:单链表可能有环,也可能无环。给定两个单链表的头节点 head1 和 head2, 这两个链表可能相交,也可能不相交。请实现一个函数,如果两个链表相交,请返回相交 的第一个节点;如果不相交,返回 null 即可。

首先,感谢程云老师的分享!以下是本问题的解决方法整理。

思路:

       链表分有环链表和无环链表,如果两个链表存在相交,则只有两种可能,两个链表都无环或者都有环。

(1)如果链表都无环,则先判断链表的尾指针是否一样,如果不一样,则没有相交。如果一样,则找出两个链表的长度差,将两个链表从距离尾节点同样的距离进行扫描,如果相交,则必然有一处扫描节点相同。实例数据List1:1->2->3->4->5->6->7->null,List2:0->9->8->6->7->null,第一个相交节点为6

示例图如下,


                                                                                                                   

(2)如果链表都有环,则只肯能有下面两种情况(如下图)。两种情况区分的方法为:入环点是否相同。

         如果相同则为第一种情况:那么查找第一个相交点与无环的单链表相交找第一个交点的方法一样。

         如果入环点不同,则为第二种情况,这个相交点或者为list1 的入环点loop1或者为list2的入环点loop2。

情况1实例数据(List1:1->2->3->4->5->6->7->4,List2:0->9->8->2->3->4->5->6->7->4,第一个交点为2)

情况2实例数据(List1:1->2->3->4->5->6->7->4,List2:0->9->8->6->7->4->5->6,第一个交点为4或6)

                                              

下面为实现代码

[java]  view plain  copy
  1. public static class Node {  
  2.         public int value;  
  3.         public Node next;  
  4.   
  5.         public Node(int data) {  
  6.             this.value = data;  
  7.         }  
  8.     }  
  9. /*判断是否相交,如果相交,得到第一个相交点*/  
  10.     public static Node getIntersectNode(Node head1, Node head2) {  
  11.         if (head1 == null || head2 == null) {  
  12.             return null;  
  13.         }  
  14.         Node loop1 = getLoopNode(head1);  
  15.         Node loop2 = getLoopNode(head2);  
  16.         if (loop1 == null && loop2 == null) {  
  17.             return noLoop(head1, head2);  
  18.         }  
  19.         if (loop1 != null && loop2 != null) {  
  20.             return bothLoop(head1, loop1, head2, loop2);  
  21.         }  
  22.         return null;  
  23.     }  
  24. /* 
  25.  * 判断是否存在环,如果存在,则找出环的入口点。 
  26.  * 入口点找法:快慢指针,块指针走两步,满指针走一步,如果存在循环,则在慢指针走完环前,总会和快指针相遇。 
  27.  * 从头指针和相遇点同时向后走,相遇的点必定是入口点。*/  
  28.     public static Node getLoopNode(Node head) {  
  29.         if (head == null || head.next == null || head.next.next == null) {  
  30.             return null;  
  31.         }  
  32.         Node n1 = head.next; // n1 -> slow  
  33.         Node n2 = head.next.next; // n2 -> fast  
  34.         while (n1 != n2) {  
  35.             if (n2.next == null || n2.next.next == null) {  
  36.                 return null;  
  37.             }  
  38.             n2 = n2.next.next;  
  39.             n1 = n1.next;  
  40.         }  
  41.         n2 = head; // n2 -> walk again from head  
  42.         while (n1 != n2) {  
  43.             n1 = n1.next;  
  44.             n2 = n2.next;  
  45.         }  
  46.         return n1;  
  47.     }  
  48. /*无环时的判断方法*/  
  49.     public static Node noLoop(Node head1, Node head2) {  
  50.         if (head1 == null || head2 == null) {  
  51.             return null;  
  52.         }  
  53.         Node cur1 = head1;  
  54.         Node cur2 = head2;  
  55.         int n = 0;  
  56.         while (cur1.next != null) {  
  57.             n++;  
  58.             cur1 = cur1.next;  
  59.         }  
  60.         while (cur2.next != null) {  
  61.             n--;  
  62.             cur2 = cur2.next;  
  63.         }  
  64.         if (cur1 != cur2) {  
  65.             return null;  
  66.         }  
  67.         cur1 = n > 0 ? head1 : head2;  
  68.         cur2 = cur1 == head1 ? head2 : head1;  
  69.         n = Math.abs(n);  
  70.         while (n != 0) {  
  71.             n--;  
  72.             cur1 = cur1.next;  
  73.         }  
  74.         while (cur1 != cur2) {  
  75.             cur1 = cur1.next;  
  76.             cur2 = cur2.next;  
  77.         }  
  78.         return cur1;  
  79.     }  
  80. /*有环时的判断方法*/  

[java]  view plain  copy
  1. public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) {  
  2.         Node cur1 = null;  
  3.         Node cur2 = null;  
  4.         if (loop1 == loop2) {  
  5.             cur1 = head1;  
  6.             cur2 = head2;  
  7.             int n = 0;  
  8.             while (cur1 != loop1) {  
  9.                 n++;  
  10.                 cur1 = cur1.next;  
  11.             }  
  12.             while (cur2 != loop2) {  
  13.                 n--;  
  14.                 cur2 = cur2.next;  
  15.             }  
  16.             cur1 = n > 0 ? head1 : head2;  
  17.             cur2 = cur1 == head1 ? head2 : head1;  
  18.             n = Math.abs(n);  
  19.             while (n != 0) {  
  20.                 n--;  
  21.                 cur1 = cur1.next;  
  22.             }  
  23.             while (cur1 != cur2) {  
  24.                 cur1 = cur1.next;  
  25.                 cur2 = cur2.next;  
  26.             }  
  27.             return cur1;  
  28.         } else {  
  29.             cur1 = loop1.next;  
  30.             while (cur1 != loop1) {  
  31.                 if (cur1 == loop2) {  
  32.                     return loop1;  
  33.                 }  
  34.                 cur1 = cur1.next;  
  35.             }  
  36.             return null;  
  37.         }  
  38.     }  
另:判断是否单链表是否有环可以使用哈希表进行判断。

 
最后,关于如何找环的入口点问题,可以参考文章:http://blog.csdn.net/wongson/article/details/8019228,
                
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值