如何检测一个链表中是否有环,如下图所示:
检测方法:快慢指针法
思路:
设置快慢两个指针P1、P2,同时遍历链表,P1是一次遍历两个节点,P2一次遍历一个节点,
如果没有环,两个指针会先后遍历到链表末尾,
如果有环,一直循环两个指针最终会相遇(可理解为速度不同的两个人在400m环形跑道上跑步,一直跑下去,肯定会相遇),若相遇,则证明该链表有环。
实现:
部分代码基于单链表相关实现, 可移步前去看
package com.example.demo.linkedlist;
/**
* 判断链表中是否有环
* Created by xinan on 2021/02/24
*/
public class HasLoop {
/**
* 快慢指针法
* @param head 头节点
* @return 是否有环(true: 有环 )
*/
private static boolean hasLoop(Node head) {
if (head == null) {
return false;
}
Node p = head;
Node q = head.next;
while (p != null && q.next != null) {
p = p.next;
q = q.next.next;
// 已到链尾
if (q == null) {
return false;
} else if (p == q) {
return true;
}
}
return false;
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
SingleLinkedList linkedList = new SingleLinkedList();
linkedList.addLast(1);
linkedList.addLast(3);
linkedList.addLast(5);
linkedList.addLast(2);
linkedList.addLast(8);
// 创造环(将链表中最后一个结点指向下标为1的结点)
linkedList.getByIndex(linkedList.length() - 1).setNext(linkedList.getByIndex(1));
boolean hasLoop = hasLoop(linkedList.head);
System.out.println("hasLoop: " + hasLoop);
}
}