1.题目
判断一个单链表是否有环,并且环的入口是哪个结点
2.解法
public class Sort {
/**
* 方法功能:判断链表是否有环
* 输入参数: head 链表的头结点
* 返回值为null,无环,否则返回slow和fast相遇点的结点
*/
public static Node isLoop(Node head){
if(head == null || head.next == null){
return null;
}
// 设置起始点相同的快慢指针
Node slow, fast;
slow = fast = head.next;
// 让它退出的条件是什么, fast为null
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
// 正好移动判断,然后退出
if(slow == fast){
return slow;
}
}
return null;
}
/**
* 方法功能: 得到环入口点
* 输入参数: 链表的头结点, 快慢结点的相遇点
* 输出: 环入口点
*/
public static Node findLoopNode(Node head, Node meetNode){
Node first = head.next;
Node second = meetNode;
while(first != second){
first = first.next;
second = second.next;
}
return first;
}
/* 构造链表 */
public static Node constructList(){
// 假的头结点
Node head = new Node(-1);
Node cur = head;
Node tmp = null;
for(int i = 1; i < 8; i++){
tmp = new Node(i);
cur.next = tmp;
cur = tmp;
}
cur.next = head.next.next.next;
return head;
}
public static void main(String[] args) {
// 1.构造链表
Node head = Sort.constructList();
// 2.寻找相遇点
Node meetNode = Sort.isLoop(head);
if (meetNode != null){
System.out.println("此单链表有环,相遇点为" + meetNode.data);
Node loopNode = Sort.findLoopNode(head, meetNode);
System.out.println("环的入口点" + loopNode.data);
} else{
System.out.println("此链表无环!");
}
}
}
只需要对链表遍历一次,时间复杂度为O(n), 空间复杂度为O(1)