检测是否有环-leetcode 141
方法一:哈希表
我们可以通过检查一个结点此前是否被访问过来判断链表是否为环形链表。常用的方法是使用哈希表
public boolean hasCycle(ListNode head) {
ListNode temp1 = head;
Set<ListNode> set = new HashSet<>();
while (temp1 != null){
if(set.contains(temp1)){
return true;
}else {
set.add(temp1);
}
temp1 = temp1.next;
}
return false;
}
时间复杂度和空间复杂度都是o(n)
方法二:双指针
通过使用具有 不同速度 的快、慢两个指针遍历链表,空间复杂度可以被降低至 O(1)。慢指针每次移动一步,而快指针每次移动两步。
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;
}
时间复杂度:o(n)
空间复杂度:o(1)
返回成环的第一个结点-leetcode 142
哈希表
public ListNode detectCycle(ListNode head) {
ListNode temp = head;
Set<ListNode> set = new HashSet<>();
while (temp != null) {
if(set.contains(temp)){
return temp;
}else {
set.add(temp);
}
temp = temp.next;
}
return null;
}
时空复杂度都为o(n)
双指针法
https://leetcode-cn.com/problems/linked-list-cycle-ii/solution/
public ListNode detectCycle(ListNode head) {
ListNode fast = head, slow = head;
while (true) {
if (fast == null || fast.next == null) {return null;}
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {break;}
}
fast = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return fast;
}
时间复杂度:o(n)
空间复杂度:o(1)