一. 题目
1. 问题1
2. 问题2
二. 思路
1. 哈希表
将遍历过的节点存在哈希表,然后依次往下走,若遇到已在哈希表中的,说明存在环。
时间O(n), 空间O(n)。
2. 标记法
将走过的节点的值标记为正无穷,遇到标记值就是存在环。
时间O(n), 空间O(1)。
3. 双指针
①问题1
②问题2
4. 统计节点数量
每遍历一个点,cnt+1,若cnt超出给定范围,说明存在环。
三. 代码
2. 标记法
class ListNode
{
int val;
ListNode next;
ListNode(int x)
{
val = x;
next = null;
}
}
class Solution
{
static final int INF = Integer.MAX_VALUE;
public boolean hasCycle(ListNode head)
{
ListNode ph = head;
boolean ans = false;
while (ph != null)
{
if (ph.val == INF)
{
ans = true;
break;
}
ph.val = INF;
ph = ph.next;
}
return ans;
}
}
3. 双指针
①问题1
class ListNode
{
int val;
ListNode next;
ListNode(int x)
{
val = x;
next = null;
}
}
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;
}
}
②问题2
class Solution
{
public ListNode detectCycle(ListNode head)
{
ListNode slow = head, fast = head;
while (fast != null && fast.next != null)
{
slow = slow.next;
fast = fast.next.next;
if (slow == fast)
{
ListNode ans = head;
while (ans != slow)
{
ans = ans.next;
slow = slow.next;
}
return ans;
}
}
return null;
}
}
4. 统计节点数量
class Solution
{
public ListNode detectCycle(ListNode head)
{
for (ListNode l = head, r = head; l != null; l = l.next, r = l)
for (int i = 0; i < (int) 1e4; ++i)
{
r = r.next;
if (r == null) break;
if (l == r) return l;
}
return null;
}
}