链表节点结构定义:
package case56_EntryNodeOfLoop;
/**
* 单链表的节点结构定义
*
* @author WangSai
*
*/
public class ListNode {
int data;
ListNode next;
public ListNode() {
}
public ListNode(int data) {
this.data = data;
}
}
链表中环的入口结点代码实现:
package case56_EntryNodeOfLoop;
/**
* 题目:一个链表中包含环,如何找出环的入口节点?例如在下图的链表中,环的入口节点是节点3。
*
* N1 ——>N2 ——>N3 ——>N4 ——>N5 ——>N6 ——>N7 ——>N8 ——>N9 ——>N10 ——>N11 ——>N12
* ............^—————————————<—————————————<—————————————<—————————————v
*
* 思路:
*
* 1,首先判断链表中是否有环。方法:定义两个指针,fast和slow指向head,fast走的快,slow走的慢。若有环则fast会追上slow,
* 并且相遇的节点就是环中的节点。
*
* 2,若有环,则从相遇的节点开始统计环中的节点数n
*
* 3,再定义两个指针p1,p2从链表的头开始,p1先走n步,然后,p2和p1一起向前走,当第一次相遇时,便是环形链表的入口节点。
*
* @author WangSai
*
*/
public class EntryNodeOfLoop {
/**
* 判断链表中是否存在环?定义两个指针一个走的 快fast,一个走的慢slow,如果快的fast和慢的slow相遇了,说明存在环,并且返回相遇的点。
* 若不存在则返回null。
*
* @param head,链表的头结点
* @return 环中相遇的节点,若不存在环则返回null
*/
private static ListNode meetingNode(ListNode head) {
// 异常检测
if (head == null)
return null;
// 定义两个指针,一个走的快,一个走的慢
ListNode fast = head;
ListNode slow = head;
while (fast != null) {
fast = fast.next;
if (fast == null)
return null;
fast = fast.next;
slow = slow.next;
if (fast == slow) {
return slow;
}
}
return null;
}
/**
* 找到相遇的点后,计算环中有多少个点
*
* @param node,环中任意的一个节点
* @return 环中有多少个节点
*/
private static int numOfNodeInLoop(ListNode node) {
if (node == null)
return 0;
int count = 1;
ListNode temp = node;
temp = temp.next;
while (node != temp) {
count++;
temp = temp.next;
}
return count;
}
/**
* 寻找环的入口节点。定义两个指针p1,p2。p1先走n步,然后,p1 p2一起向前走,当他们相遇时,就是环形链表的入口。
*
* @param head,链表的头结点
* @param num,链表中环形链表中的节点数量
* @return 链表的环形入口
*/
private static ListNode myEntryNode(ListNode head, int num) {
// num为0,说明没有环
if (num == 0)
return null;
// fast先走num步,然后,slow和fast一起向前走。当fast和slow相遇时,就是入口的点。
ListNode fast = head;
ListNode slow = head;
while (num > 0) {
fast = fast.next;
num--;
}
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
/**
* @param args
*/
public static void main(String[] args) {
// 链表有环
test1();
// 单链表,没有环
test2();
// 空链表
test3();
// 环形链表,链表尾节点指向头结点
test4();
}
/**
* 链表有环
*/
public static void test1() {
// TODO Auto-generated method stub
ListNode head = new ListNode(1);
ListNode n2 = new ListNode(2);
ListNode n3 = new ListNode(3);
ListNode n4 = new ListNode(4);
ListNode n5 = new ListNode(5);
ListNode n6 = new ListNode(6);
ListNode n7 = new ListNode(7);
ListNode n8 = new ListNode(8);
ListNode n9 = new ListNode(9);
head.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
n6.next = n7;
n7.next = n8;
n8.next = n9;
n9.next = n8;
ListNode entryNode3 = myEntryNodeInLoop(head);
System.out.println(entryNode3.data);
}
/*
* 单链表,没有环
*/
public static void test2() {
// TODO Auto-generated method stub
ListNode head = new ListNode(1);
ListNode n2 = new ListNode(2);
ListNode n3 = new ListNode(3);
ListNode n4 = new ListNode(4);
ListNode n5 = new ListNode(5);
ListNode n6 = new ListNode(6);
ListNode n7 = new ListNode(7);
ListNode n8 = new ListNode(8);
ListNode n9 = new ListNode(9);
head.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
n6.next = n7;
n7.next = n8;
n8.next = n9;
ListNode entryNode3 = myEntryNodeInLoop(head);
System.out.println(entryNode3);
}
/*
* 空链表
*/
public static void test3() {
ListNode entryNode1 = myEntryNodeInLoop(null);
System.out.println(entryNode1);
}
/*
* 链表尾节点指向头节点
*/
public static void test4() {
// TODO Auto-generated method stub
ListNode head = new ListNode(1);
ListNode n2 = new ListNode(2);
ListNode n3 = new ListNode(3);
ListNode n4 = new ListNode(4);
ListNode n5 = new ListNode(5);
ListNode n6 = new ListNode(6);
ListNode n7 = new ListNode(7);
ListNode n8 = new ListNode(8);
ListNode n9 = new ListNode(9);
head.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
n6.next = n7;
n7.next = n8;
n8.next = n9;
n9.next = head;
ListNode entryNode3 = myEntryNodeInLoop(head);
System.out.println(entryNode3.data);
}
private static ListNode myEntryNodeInLoop(ListNode head) {
// 是否有环,若有环则返回环中的任意结点;若没有则返回null
ListNode nodeInloop = meetingNode(head);
// 统计环中有多少个节点
int numInLoop = numOfNodeInLoop(nodeInloop);
System.out.println("环中有多少个节点:" + numInLoop);
// 返回环的入口节点
ListNode entryNode = myEntryNode(head, numInLoop);
return entryNode;
}
}