LinkedList 成环判断
- Leetcode 算法题 (141. Linked List Cycle, 142. Linked List Cycle II)
- Floyd Cycle-Detection Algorithm 方法应用
Background
给出一个链表(LinkedList)的第一个Node,判断该链表是否成环,环的长度和起点(Node).
Floyd Cycle-Detection Algorithms
Floyd’s cycle-finding algorithm is a pointer algorithm that uses only two pointers, which move through the sequence at different speeds.
算法思路:
- 两个指针一起在链表头部跑,一个快指针一次跑2个Node , 一个慢指针一次跑一个Node.
- 当快指针跑到一个空的节点,该链表未能成环. (慢指针永远跑在快指针的后面)
- 当慢指针和快指针跑到同一个节点,该链表成环.
- 跑到同一个指针后,将慢指针移动回链表头部,两个指针同时跑,每次只跑一个节点. 两个指针再次相遇的节点为链表成环的环起点.
- 跑到同一个指针后,将快指针停止,慢指针再次移动,每次移动一个Node, 再次相遇时所通过的节点数就是链表环的长度.
算法分析:
- Time-Complexity Analysis:
- 如果链表未能成环,则时间为整个链表遍历的时间
B i g − O N o t a t i o n = O ( n ) t i m e c o m p l e x i t y Big-O \; Notation = O(n)\; time\; complexity Big−ONotation=O(n)timecomplexity
- 如果链表成环,则需要用 O(n) 来判断成环 (n是考虑链表长度+环状的长度*循环遍历次数), 额外多循环一次 O(n + 环长度) 来寻找环的长度,额外循环一次链表长度来寻找成环的起点. - Space-Complexity Analysis: 该算法是 two pointer 算法的扩展设计, 只需要使用两个指针, 因此时间复杂度为 O(1) space complexity.
Leetcode 141. Linked List Cycle
问题描述
给定一个链表的第一个节点,查询该链表是否存在环.
Example 1 (pos 不作为输入值在题目中给出, 输入值只有 value 3 所存在的第一个 ListNode)
Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 1st node (0-indexed).
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
解决方案
public boolean hasCycle(ListNode head) {
if (head == null) return false;
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
return false;
}
Leetcode 142. Linked List Cycle II
问题描述
给定一个链表的第一个节点,查询该链表环的起点 ListNode. 如果该链表不成环,则返还 null.
Example 1. (pos 不作为输入值在题目中给出, 输入值只有 value 3 所存在的第一个 ListNode)
Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
解决方案
public ListNode detectCycle(ListNode head) {
if (head == null) return null;
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
slow = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return fast;
}
}
return null;
}