查看链表是否有环?两种方式
思路:就是因为有环,所以是没有尾节点,也就是 node.next 永远都是有值的。可以通过两个前进速度不同的节点去循环,如果有相遇的时刻说明有环。
- 首先创建Node节点
private class Node {
private Object data;
Node next;
public Node() {
data = null;
}
public Node(Object data) {
this.data = data;
}
}
- 创建有环链表
private Node createLink(){
// 构造链表
Node head = new Node();
head.next = null;
Node temp = null;
Node cur = head;
for (int i = 0; i < 10; i++) {
temp = new Node();
temp.data = i;
temp.next = null;
cur.next = temp;
cur = temp;
}
// Node tem = head;
// while (tem.next != null) {
// tem = tem.next;
// // 输出 0123456789
// System.out.print(tem.data);
// }
// 添加环
cur.next = head.next.next.next;
// Node tem1 = head;
// while (tem1.next != null) {
// tem1 = tem1.next;
// // 因为有了环。。无限输出。。。卡死输出台
// System.out.print(tem1.data);
// }
return head;
}
- 方式一:查看是否有环 根据是否返回有具体的点 返回 null 代表无环
private Node isLoop(Node head) {
// 查看是否有环 思路:如果有环,快的和慢的一定会有一点碰到一起
if (head == null || head.next == null) {
return null;
}
Node slow = head.next;
Node fast = head.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return slow;
}
}
return null;
}
- 方式二:通过HashMap ,将节点引用添加到 HaskMap 中,如果存在引用说明有环,不存在说明无环。
private Node isLoopForHashMap(Node head) {
HashSet<Node> hashSet = new HashSet<Node>();
Node tem = head;
while (tem.next != null) {
tem = tem.next;
if (hashSet.contains(tem)) {
return tem;
}
hashSet.add(tem);
}
return null;
}
- 查找环的入口点
public Node findLoopNode(Node head, Node meetNode) {
Node first = head.next;
Node second = meetNode;
while (first != second) {
first = first.next;
second = second.next;
}
return first;
}
- 调用如下
@Test
public void testLink() {
// 创建链表
Node head = createLink();
// 查找是否有环 有环则返回头节点
Node node = isLoop(head);
// Node node = isLoopForHashMap(head);
if (node == null) {
System.out.println("无环");
} else {
System.out.println("有环");
}
Node meetNode = findLoopNode(head, node);
System.out.println(meetNode.data);
}