#141 環形鏈表
給定一個鏈表,判斷鏈表中是否有環。
爲了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鏈表中沒有環。
輸入:head = [3,2,0,-4], pos = 1 輸出:true 解釋:鏈表中有一個環,其尾部連接到第二個節點。
輸入:head = [1,2], pos = 0 輸出:true 解釋:鏈表中有一個環,其尾部連接到第一個節點。
方法一:哈希表
我們可以通過檢查一個結點此前是否被訪問過來判斷鏈表是否爲環形鏈表。常用的方法是使用哈希表。
遍歷所有結點並在哈希表中存儲每個結點的引用(或內存地址)。如果當前結點爲空結點 null(即已檢測到鏈表尾部的下一個結點),那麼我們已經遍歷完整個鏈表,並且該鏈表不是環形鏈表。如果當前結點的引用已經存在於哈希表中,那麼返回 true(即該鏈表爲環形鏈表)。
/**java
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
set<ListNode> hash = new HashSet<>();
while(head!=null){ // 遍歷節點
if(hash.contains(head)){ // 判斷哈希表裏是否有當前值
return true;
}else{ // 如果沒有,直接加入哈希表
hash.add(head);
}
head = head.next;
}
return false;
}
}
/**javascript
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function(head) {
let map = new Map()
while(head){
if(map.has(head))
return true;
map.set(head,true)
head = head.next;
}
return false;
};
方法二:雙指針遍歷
// java
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null) // 結束條件
return false;
ListNode slow = head;
ListNode fast = head.next;
while(slow != fast){
if(fast == null || fast.next == null){
return false;
}
slow = slow.next; // 慢指針每次走一步
fast = fast.next.next; // 快指針每次走兩步
}
return true;
}
}
var hasCycle = function(head) {
let slow = head;
let fast = head;
while(slow && fast && fast.next){
slow = slow.next;
fast = fast.next.next;
if(slow === fast)
return true;
}
return false;
};
方法三:劍走偏鋒
利用JSON.stringify()不能序列化含有循環引用結構
var hasCycle = function(head) {
try{
JSON.stringify(head);
return false;
}
catch(err){
return true;
}
};