zoukankan      html  css  js  c++  java
  • 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 }
    View Code

    运行结果:

    1.有交点:

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

    2.无交点:

    这两个单链表不相交!

  • 相关阅读:
    占卜DIY
    飞行员兄弟
    给树染色
    国王游戏
    雷达设备
    畜栏预定
    防晒
    去雨系列论文笔记
    First day
    如何用fprintf写十六进制 并控制格式
  • 原文地址:https://www.cnblogs.com/wuzetiandaren/p/4251372.html
Copyright © 2011-2022 走看看