转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4251303.html
声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明。谢谢。
题目:判断一个单链表是否有环,如果有环,求出环的入口节点。
题目分析:
建一个待头节点的单链表,有两个指针p,q最开始都指向第一个真正节点,p,诶次走1步,q每次走两步,若有环,p和q会在环中的某个节点处相遇。具体分析如下图所示:
java实现:
1 package com.interview; 2 3 public class _7_1JudgeListCycle { 4 5 /** 6 * @param args 7 */ 8 public static int x=0, y=0, k=0; //分别记录圈外链表的长度,圈的长度,第一次相遇时慢指针走的总长度 9 public static void main(String[] args) { 10 Node first = createList(24, 6); //创建有环链表 11 judge(first); //判断该单链表是否有环 12 } 13 14 //创建带头节点的链表、参数为:链表总长度,入口节点 15 public static Node createList(int size, int entry){ 16 /** 1)用尾插法构建单链表,此处构建有环单链表,让node24指向node6*/ 17 Node first = new Node(null,null); //头节点 18 Node r = first; //指向链表的尾节点 19 Node t = null; //指向环的入口节点 20 for(int i=1;i<=size;i++){ 21 Node node = new Node((new Stu(""+i,"小牛犊@"+i)),null); 22 r.next = node; 23 r = node; 24 if(i==entry) t = r; //让环的入口为节点6 25 } 26 r.next = t; //若是构建无环单链表,此处 r.next = null; 27 return first; 28 } 29 30 //判断是否有环 31 public static void judge(Node first){ 32 /** 2)判断是否有环若pq先重合则有环,若q先指向null,则无环 */ 33 Node p = first.next; 34 Node q = first.next; 35 String flag = "0"; //标记有环还是无环,0-无环,1-有环 36 if(p==null){ //空链表 37 System.out.println("链表为空!"); 38 return; 39 } 40 k = 1; 41 while(q.next!=null && q.next.next!=null){ 42 k++; 43 p=p.next; 44 q=(q.next).next; 45 if(q.equals(p)){ 46 flag="1"; 47 System.out.println("p和q相遇了,该单链表有环!"); 48 break; 49 } 50 } 51 52 /** 3)有环的时候求环的入口节点 */ 53 if(flag.equals("1")){ //有环 54 p=first.next; //p重新指向第一个节点 55 searchEnter(p,q); 56 } 57 else{ //是因为q走到了尽头才跳出循环的,无环 58 System.out.println("该单链表没有环!"); 59 } 60 } 61 62 //求环的入口节点 63 public static void searchEnter(Node p, Node q){ 64 x=1; 65 while(!q.equals(p)){ 66 x++; //求圈外长度 67 p=p.next; 68 q=q.next; 69 } 70 Node r = q.next; //为了求圈长设定的 71 y = 1; //求圈长度 72 while(r!=q){ 73 r = r.next; 74 y++; 75 } 76 77 System.out.println("入口节点是链表中的第"+ x+"个节点!"); 78 System.out.println("入口节点的no: "+ p.stu.no); 79 System.out.println("入口节点的名字为: "+ p.stu.name); 80 System.out.println("圈的长度是:"+ y); 81 System.out.println("第一次相遇时,慢指针在圈内走的长度为:"+ (k-x)); 82 System.out.println("第一次相遇时,快指针在圈内走了:"+ (k/y)+"圈"); 83 System.out.println("第二次相遇时,快指针在圈内又走了:"+ (k/y-1)+"圈"); 84 } 85 86 //链表节点的数据结构 87 static class Node { 88 public Stu stu; 89 public Node next; 90 91 public Node() { 92 super(); 93 // TODO Auto-generated constructor stub 94 } 95 public Node(Stu stu, Node next) { 96 super(); 97 this.stu = stu; 98 this.next = next; 99 } 100 } 101 102 //节点立里的元素 103 private static class Stu { 104 public String no; 105 public String name; 106 public Stu(String no, String name) { 107 super(); 108 this.no = no; 109 this.name = name; 110 } 111 } 112 }
运行效果:
1.无环:
该单链表没有环!
2.有环:
p和q相遇了,该单链表有环!
入口节点是链表中的第6个节点!
入口节点的no: 6
入口节点的名字为: 小牛犊@6
圈的长度是:19
第一次相遇时,慢指针在圈内走的长度为:14
第一次相遇时,快指针在圈内走了:1圈
第二次相遇时,快指针在圈内又走了:0圈
时间: 2024-10-13 05:46:04