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

转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4251372.html

声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明。谢谢。

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

题目分析:

  创建A,B两个单链表,将B的尾部指向头部,若两个单链表相交,则交点必为环的入口,这就又变成上边判断一个单链表是否有环的问题了。

  注: 若两个单链表相交,则相交之后的那些节点比都是一样的(相交之后的长度是一样的),否则若一长一短或者相交之后有分叉,则在短链表末尾或者分叉节点处,该节点将有两个next分别指向两边的链表,这就不是单链表了。

源码实现:

  1 package com.interview;
  2
  3 /**
  4  * 判断两个单链表是否相交,若相交,求出第一个交点
  5  * 方法:创建A,B两个单链表,将B的尾部指向头部,若两个单链表相交,则交点必为环的入口
  6  *   若两个单链表相交,则相交之后的那些节点比都是一样的(相交之后的长度是一样的),
  7  *   否则若一长一短或者相交之后有分叉,则在锻炼表末尾或者分叉节点处,该节点将有
  8  *   两个next分别指向两边的链表,这就不是单链表了
  9  * @author wjh
 10  *
 11  */
 12 public class _7_2JudgeListCross {
 13
 14     /**
 15      * @param args
 16      */
 17     //分别记录相交前A表的长度,B链表(圈)的长度,第一次相遇时慢指针走的总长度
 18     public static int x=0, y=0, k=0;
 19     public static void main(String[] args) {
 20         //1)创建两个相交的链表
 21         Node nodeA = createList("A", 28);
 22         Node nodeB = createList("B", 3);
 23         Node tail = createTail(3);
 24         nodeA = merge(nodeA, tail);
 25         nodeB = merge(nodeB, tail);
 26         //2)将B的尾节点指向B的第一个节点 ,此时若相交,A的结构就变成带环单链表了,
 27             //若不相交则遍历A会走到null
 28         Node r = findTail(nodeB);  //若要求A B的长度,则在上面遍历nodeA,nodeA
 29         r.next = nodeB.next;
 30         judge(nodeA);
 31
 32     }
 33
 34
 35     //创建带头节点的无环单链表的相较之前的部分
 36     public static Node createList(String name, int k){
 37         /**  1)用尾插法构建单链表,此处构建有环单链表,让node24指向node6*/
 38         Node first = new Node(null,null);    //头节点
 39         Node r = first;   //指向链表的尾节点
 40         for(int i=1;i<=k;i++){  //根据传入参数创建相交之前的部分节点
 41             Node node = new Node("猫狗_"+name+"_"+i,null);
 42             r.next = node;
 43             r = node;
 44         }
 45         r.next = null;       //若是构建无环单链表,此处   r.next = null;
 46         return first;
 47     }
 48
 49     //创建带头节点的无环单链表的相较之后的相同的部分
 50     public static Node createTail(int k){
 51         Node first = new Node(null,null);    //头节点
 52         Node r = first;   //指向链表的尾节点
 53         for(int i=1;i<=k;i++){  //创建相交之后的部分节点
 54             Node node = new Node("相同节点@"+i,null);
 55             r.next = node;
 56             r = node;
 57         }
 58         r.next = null;       //若是构建无环单链表,此处   r.next = null;
 59         return first;
 60     }
 61
 62     //将相交之前和相交之后的链表穿起来
 63     public static Node merge(Node first, Node second){
 64         Node r = first;   //记录前面链表的尾部节点
 65         while(r.next!=null){
 66             r = r.next;
 67         }
 68         //因为second是后面链表的头节点,是空的,头节点下一个节点才是真正的节点
 69         r.next = second.next;
 70         return first;
 71     }
 72
 73     //找到一个链表的尾节点
 74     public static Node findTail(Node node){
 75         Node r = node;   //记录前面链表的尾部节点
 76         while(r.next!=null){
 77             r = r.next;
 78         }
 79         return r;
 80     }
 81
 82     //判断是否有环
 83     public static void judge(Node first){
 84         /**  2)判断是否有环若pq先重合则有环,若q先指向null,则无环    */
 85         Node p = first.next;
 86         Node q = first.next;
 87         String flag = "0";  //标记有环还是无环,0-无环,1-有环
 88         if(p==null){     //空链表
 89             System.out.println("链表为空!");
 90             return;
 91         }
 92         k=1;
 93         while(q.next!=null && q.next.next!=null){
 94             k++;      //记录相遇时p指针走的长度,k从0开始,因为k已经加过1了才判断pq是否相等
 95             p=p.next;
 96             q=(q.next).next;
 97             if(q.equals(p)){
 98                 flag="1";
 99                 System.out.println("p和q相遇了,这两个单链表相交!");
100                 break;
101             }
102         }
103
104         /**  3)有环的时候求环的入口节点    */
105         if(flag.equals("1")){    //有环
106             p=first.next; //p重新指向第一个节点
107             searchEnter(p,q);
108         }
109         else{   //是因为q走到了尽头才跳出循环的,无环
110             System.out.println("这两个单链表不相交!");
111         }
112     }
113
114     //求环的入口节点
115     public static void searchEnter(Node p, Node q){
116         x=1;
117         while(!q.equals(p)){
118             x++;  //求圈外长度
119             p=p.next;
120             q=q.next;
121         }
122         Node r = q.next;   //为了求圈长设定的
123         y = 1;     //求圈长度
124         while(r!=q){
125             r = r.next;
126             y++;
127         }
128         System.out.println("相交节点是A链表中的第"+ x+"个节点!");
129         System.out.println("相交节点的名字为: "+ p.name);
130         System.out.println("B链表的长度是:"+ y);
131         System.out.println("第一次相遇时,慢指针在B圈内走的长度为:"+ (k-x));
132         System.out.println("第一次相遇时,快指针在B圈内走了:"+ (k/y)+"圈");
133         System.out.println("第二次相遇时,快指针在B圈内又走了:"+ (k/y-1)+"圈");
134     }
135
136
137     //创建一个私有的节点类
138     private static class Node {
139         public String name;
140         public Node next;
141         public Node(String name, Node next) {
142             super();
143             this.name = name;
144             this.next = next;
145         }
146     }
147 }

运行结果:

1.有交点:

p和q相遇了,这两个单链表相交!
相交节点是A链表中的第29个节点!
相交节点的名字为: 相同节点@1
B链表的长度是:6
第一次相遇时,慢指针在B圈内走的长度为:2
第一次相遇时,快指针在B圈内走了:5圈
第二次相遇时,快指针在B圈内又走了:4圈

2.无交点:

这两个单链表不相交!

时间: 2024-08-27 07:24:19

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

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

/* 问题: 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

判断两个单链表是否相交

题目描述: 给定两个单链表的头节点head1和head2,如何判断两个链表是否相交?相交的话返回true,不想交的话返回false. 给定两个链表的头结点head1和head2.请返回一个bool值代表它们是否相交. 链表中节点的类型设置如下: class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } 思路: 1.首先判断是否有环, 若两个链表都没有环,则进行无环单链表判断是否相

【算法导论学习-23】两个单链表(single linked)求交点

问题:A.B两个单链表如果有交点,返回第一个交点在A中的位置(链表头结点位置为0). 分析:A.B如果有交点,交点的后继一定也是交点,所以一定是Y型相交,所以算法的思想如下 1)  求得A.B的长度,比如ALength,Blength 2)  判断ALength,Blength谁大,比如Alength>Blength 3)  Alength移动到Alength-Blength的位置,开始判断每个节点是否相等,相等则退出. 以本博客中"[算法导论学习-20]单链表(single linked

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

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

判断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

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

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

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

思想: 如果它们相交,则最后一个节点一定是共有的. 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