判断两个单链表是否相交

题目描述:

  给定两个单链表的头节点head1和head2,如何判断两个链表是否相交?相交的话返回true,不想交的话返回false。

  给定两个链表的头结点head1head2。请返回一个bool值代表它们是否相交。

  链表中节点的类型设置如下:

class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}

思路:

  1、首先判断是否有环,

  • 若两个链表都没有环,则进行无环单链表判断是否相交,进入2;
  • 若两个链表一个有环一个无环,则直接判断不相交;
  • 若两个链表都有环,则分别得到每个链表的入环节点node1,node2,然后进行有环单链表判断是否相交,进入3;

  判断是否有环的方法如下:

 1 /**
 2  * 判断链表是否有环
 3  * 判断方法是设置两个指针最初均指向头结点,然后fast每次走2步,slow每次走1步,
 4  * 如果链表没有环,则fast指针肯定先指向表尾的null
 5  * 如果有环,则fast和slow肯定会相遇。然后第一次相遇后我们将fast指针重新指向头结点,
 6  * 然后fast和slow每次都走一步直到第二次相遇,那么第二次相遇的节点即为入环的节点
 7  * @param head
 8  * @return 若有,则返回入环节点,否则,返回null
 9  */
10 public ListNode judgeRing(ListNode head){
11     if(head == null){
12         return null ;
13     }
14     ListNode fast = head ;
15     ListNode slow = head ;
16
17     while(fast != null && fast.next != null){
18         fast = fast.next.next ;
19         slow = slow.next ;
20         if(fast == slow){
21             fast = head ;
22             while(fast != slow){
23                 fast = fast.next ;
24                 slow = slow.next ;
25             }
26             return slow ;
27         }
28     }
29     return null ;
30 }

  有环时查找入环点的方法的证明过程如下:

  当fast与slow相遇时,slow还没走完链表,而fast已经在环内循环了n圈了,假设slow在相遇前走了s步,则fast走了2s步,设环长为r,有2s=s+nr,即s=nr.

  由上图可知a+x=s, x+y=r,而我们的目标是找到a的位置。设上图那个拱起的曲线的长度为y,有a+x=s=nr=(n-1)r+r=(n-1)r+y+x,则a=(n-1)r+y. 这个公式告诉我们,从链表头和相遇点分别设一个指针,每次各走一步,这两个指针必定相遇,且相遇的第一个点为环入口点

  2、无环单链表是否相交判断有多种方法:

    • 方法1:先循环链表1,将每个节点的地址进行hash计算存入哈希表,然后计算链表2的每个节点的地址的hash值,若与hash表中对应位置有值,则相交,否则不相交。
    • 方法2:见链表1与2进行首尾相连,判断新链表是否有环,若没有,则不相交,若有环,则是相交的。
    • 方法3:先计算两个链表的长度L1、L2,若L1 > L2,则先将链表1移动(L1 - L2)个节点,等到链表1和链表2剩下的长度一样的时候,一起向后移动,依次判断当前链表的节点是否相等,若相等,则相交,若到队尾还没有相等的,则不相交

  方法3的代码如下:

 1 /**
 2  * 判断两个无环链表是否相交
 3  * @param head1
 4  * @param head2
 5  * @return
 6  */
 7 public boolean judgeIntersectWithoutRing(ListNode head1,ListNode head2){
 8     int len1 = calLen(head1) ;
 9     int len2 = calLen(head2) ;
10     ListNode intsect = null ;
11     if(len1 > len2){
12         intsect = judge(head1,len1,head2,len2) ;
13     }else{
14         intsect = judge(head2,len2,head1,len1) ;
15     }
16     //判断相交的节点是否为null,返回结果
17     if(intsect != null){
18         return true ;
19     }else{
20         return false ;
21     }
22 }
23
24 /**
25  * 计算链表的长度并返回
26  * @return
27  */
28 private int calLen(ListNode head){
29     int len = 0;
30     while(head != null){
31         len++ ;
32         head = head.next ;
33     }
34
35     return len ;
36 }
37
38 /**
39  * 按长链表、短链表的顺序传入两个链表,然后进行判断
40  * 如果相交,则输出首次相交的节点,否则输出null
41  * @return
42  */
43 private ListNode judge(ListNode headLong,int lenLong,
44         ListNode headShort,int lenShort){
45     int gap = lenLong - lenShort ;
46     //将较长的链表移动到与短链表等长的位置
47     while(gap != 0){
48         headLong = headLong.next ;
49     }
50     //开始判断
51     while(headLong != null && headShort != null){
52         if(headLong == headShort){
53             return headShort ;
54         }else{
55             headLong = headLong.next ;
56             headShort = headShort.next ;
57         }
58     }
59
60     return null ;
61 }

  

  3、有环单链表是否相交的判断方法:先比较两个链表的入环节点是否相等,若想等,则相交,若不想等,则从某个链表的入环节点开始循环一周,判断是否有节点等于另一个链表的入环节点,若等于,则相交,否则不相交。

  这个有环链表的判断是在得到两个环的入环节点的基础上进行的,比较简单,就不放代码了。

时间: 2024-10-14 15:23:50

判断两个单链表是否相交的相关文章

7_2判断两个单链表是否相交,若相交,求出第一个交点

转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4251372.html 声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明.谢谢. 题目:7_2判断两个单链表是否相交,若相交,求出第一个交点. 题目分析: 创建A,B两个单链表,将B的尾部指向头部,若两个单链表相交,则交点必为环的入口,这就又变成

判断两个单链表是否相交及相交的第一个节点

/* 问题: 1.判断两个单链表是否相交 2.找出第一个相交节点 解题思路: 1.若连个链表相交则从相交节点开始以后节点都是一样的 2.通过链表长度判断然后去寻找 */ #include<stdlib.h> #include<stdio.h> /* 创建节点 */ typedef struct STU { char a; struct STU *next; }*SListNode; SListNode ListA; SListNode ListB; /* 创建链表A */ SLis

9.判断两个单链表是否相交

9.判断两个单链表是否相交 注意这里是判断是否相交.对于判断问题来讲,相对还是比较简单的.注意单链表并非不能有重复元素. 思路1:O(len1*len2) 把第一个链表的指针值逐项存在hashtable中,遍历第2个链表的每一项的指针值,如果能在第一个链表中找到,则必然相交.但是C++的STL模板中的hash不太会用.所以我使用了set集合,不过貌似set集合是使用遍历的方式来查找元素是否在集合中的,所以效率是比较低的,至少在O(len1*len2)级别. bool judgeIntersect

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

转载于:http://blog.csdn.net/happymatilian/article/details/47811161 思路: 链表分有环链表和无环链表,如果两个链表存在相交,则只有两种可能,两个链表都无环或者都有环. (1)如果链表都无环,则先判断链表的尾指针是否一样,如果不一样,则没有相交.如果一样,则找出两个链表的长度差,将两个链表从距离尾节点同样的距离进行扫描,如果相交,则必然有一处扫描节点相同.实例数据List1:1->2->3->4->5->6->7

判断两个单链表是否相交?若相交求交点

思想: 如果它们相交,则最后一个节点一定是共有的. ListNode* IsIntersect(ListNode * list1, ListNode* list2 ) {                  assert(list1 && list2);                  ListNode* l1 = list1 ;                  ListNode* l2 = list2 ;                  int cout1 = 0;         

Intersection of Two Linked Lists (判断两个单链表是否相交)

题目描述: Write a program to find the node at which the intersection of two singly linked lists begins. For example, the following two linked lists: A: a1 → a2 c1 → c2 → c3 B: b1 → b2 → b3 begin to intersect at node c1. Notes: If the two linked lists hav

判断2个单链表是否相交,并求出第一个相交结点

不考虑单链表有环的情况下 如果2个单链表相交,一定是Y型链表 1.遍历2个链表到尾结点,记录2个链表的长度x,y 2.尾结点相同,则相交. 3.从表头开始,长链表先走|x-y|步,之后2个链表一起走,判断第一个相同的点. 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 typedef struct student //定义链表结构 5 { 6 int num; 7 struct stu

判断两个单向链表是否相交

分为三种情况:第一种情况: 一个链表有环,一个链表没有环,那这两个链表不可能相交第二种情况: 两个链表都没有环第三种情况: 两个链表都有环 public class FindFirstIntersectNode { public static class Node { public int value; public Node next; public Node(int data) { this.value = data; } } /** * 分为三种情况: * 第一种情况: 一个链表有环,一个

如果判断两个单链表有交?第一个交点在哪里?

检测单链表是否有环 参考:判断单链表里面有没有环