描述
給定一個鏈表,判斷它是否有環。
樣例
給出 -21->10->4->5, tail connects to node index 1,返回 true
挑戰
不要使用額外的空間
思路
- 使用O(n)的額外空間時,在遍歷整個鏈表的過程中用一個hash表存儲當前結點的引用,如果hash表中已經存在當前結點的引用return false,否則加入hash表,如果遍歷完整個鏈表仍舊沒發現重復值證明鏈表沒環
- 定義兩個指針,一個快一個慢,設定快的跑兩步,慢的跑一步,如果有環則它們一定會相遇
兩種思路時間復雜度都是O(n)
變形題目
題目有一種變體,就是判斷兩個鏈表有沒有交集,將第一個鏈表的末指針和第二個鏈表的頭指針連接到一起,若有交集則一定存在環
代碼
/**
* Definition for ListNode.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int val) {
* this.val = val;
* this.next = null;
* }
* }
*/
- 哈希表法
public class Solution {
/*
* @param head: The first node of linked list.
* @return: True if it has a cycle, or false
*/
public boolean hasCycle(ListNode head) {
Set<ListNode> nodesSeen = new HashSet<>();
while (head != null) {
if (nodesSeen.contains(head)) {
return true;
} else {
nodesSeen.add(head);
}
head = head.next;
}
return false;
}
}
- 快慢指針
public class Solution {
/*
* @param head: The first node of linked list.
* @return: True if it has a cycle, or false
*/
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
// 注意要讓跑的快的在前面,不然沒跑完一圈就追上了
ListNode slow = head;
// 如果 fast 也賦值為 head 則在第一個結點就會跳出 while 循環
ListNode fast = head.next;
while (slow != fast) {
// 在沒追上慢指針的情況下,遍歷完了整個鏈表,證明沒有環
if (fast == null || fast.next == null) {
return false;
}
fast = fast.next.next;
slow = slow.next;
}
// slow == fast時證明有環
return true;
}
}