查看鏈表是否有環?兩種方式
思路:就是因爲有環,所以是沒有尾節點,也就是 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);
}