链表中与位置有关的计算都可以考虑使用快慢指针,左右指针,如倒数第N个节点,删除倒数第N个节点,中间节点等
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
// 通过快慢指针测试是否有环,通过一个巧妙地转换k和2k,以及相遇点的关系,即可推算出环起始点的位置
function detectCycle(head: ListNode | null): ListNode | null {
if (head === null) return null;
let dummy = new ListNode(-1);
let fast = dummy, slow = dummy;
dummy.next = head;
while (fast !== null && fast.next !== null) {
fast = fast.next.next;
slow = slow.next;
if(fast !== null && fast === slow) break;
}
if (fast === null || fast.next === null) return null; // 如果出现非环的情况发,返回null,放到循环外可以减少判断次数
// 此时可以明确是有环的情况
fast = dummy;
while (fast !== slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
};