环形链表相关题型总结
题目汇总
参考资料:
解题关键点
- 第1题的关键在于利用快慢指针,若快指针能追上慢指针,则说明有环;
- 第2题的关键在于当快慢指针第一次相遇时,再利用一个新的entry指针指向head,让其与慢指针slow同频率前进直到相遇,则相遇点即为环形链表的入口;
- 第3题主流的解法有两种:
- 当快慢指针第一次相遇之后,让快指针停住而慢指针继续前进,并且在此时开始记录慢指针前进的次数,直到慢指针重新与快指针相遇,则记录的次数即为环形链表的长度;
- 也是在快慢指针第一次i相遇之后开始记录前进的次数,直到两指针第二次相遇,则由公式:环形链表长度=(快慢指针速度差)X 前进次数=前进次数(速度差为1)。
- 第4题的解法是基于第2题的解法——找到环入口的上一个结点,并把其的next域赋值为null,断链即可。
目前已知运行最为高效的代码
class Solution {
public boolean hasCycle(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (fast == slow) return true;
}
return false;
}
}
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 (fast == slow) {
ListNode entry = head;
while (slow != entry) {
entry = entry.next;
slow = slow.next;
}
return entry;
}
}
return null;
}
}
class Solution {
public int CycleLength(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (fast == slow) {
int len = 0;
while (slow != fast) {
slow = slow.next;
++len;
}
return len;
}
}
return 0;
}
}
class Solution {
public ListNode changeCycle(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (fast == slow) {
ListNode entry = head;
while (slow.next != entry.next) {
entry = entry.next;
slow = slow.next;
}
slow.next = null;
break;
}
}
return head;
}
}