#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;
}
};