本文最后更新于:2022年8月1日 晚上
环形链表三连问:
是否有环 141
找出环的入口 142
环中节点个数
如何计算环中节点个数?
idx1和idx2相遇在环的入口, 让idx2单独在环里再走一圈, 并进行计数, 当idx2→next == idx1时, 返回count+1, 就是所谓的环中节点的个数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode* fast = head; ListNode* slow = head;
while (fast != NULL && fast->next != NULL) { fast = fast->next->next; slow = slow->next;
int cnt = 1;
if (fast == slow) { ListNode* idx1 = head; ListNode* idx2 = fast; while (idx1 != idx2) { idx1 = idx1->next; idx2 = idx2->next; }
while (idx2->next != idx1) { cnt++; idx2 = idx2->next; }
cout << cnt << endl; return idx1; } } return NULL; } };
|
1 如何判断有环 2 环内相遇点 3 环的入口点
最重要的就是找到环的入口,
数学证明:
把环形链表分为三部分
- 头节点—-》环的入口节点 的节点数是 x
- 环入口节点—》环内相遇节点 的节点数量是 y
- 相遇节点—》环入口节点 的节点数量是z
快慢指针:
fast指针每次走2步,slow指针每次走1步
当fast和slow指针相遇的时候,因为slow指针走的慢,所以走了x+y个节点;
fast指针走的快,所以肯定会追上slow指针,所以一共走了 x+y + n(y+z)个节点;fast指针肯定要在环中多走几圈才能追上slow指针;
又因为fast指针走的步数是slow指针的2倍;
所以有 2*slow走的步数 = fast走的步数,
即 2*(x+y) = x+y + n(y+z),
化简得:
x+y = n(y+z),拆出来一个y+z,则有
x + y = (n-1)*(y+z) + y + z
x = (n-1)(y+z) + z,其中n ≥ 1
当n=1,时,有 x = z ;
即 下面2个节点数是相同的
- 头节点—-》环的入口节点 的节点数是 x
- 相遇节点—》环入口节点 的节点数量是z
因此,头节点位置是已知的,先找到快慢指针的相遇节点,
然后分别从头节点和相遇节点向下走1步,相遇的节点就是 环的入口节点。
先找到快慢指针相遇的节点,然后分别从头节点和相遇节点向前走,2指针相遇的地方,就是环的入口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class Solution { public: ListNode *detectCycle(ListNode *head) {
ListNode* fast = head; ListNode* slow = head;
while (fast != NULL && fast->next != NULL) { fast = fast->next->next; slow = slow->next;
if (fast == slow) { ListNode* idx1 = head; ListNode* idx2 = fast; while (idx1 != idx2) { idx1 = idx1->next; idx2 = idx2->next; }
return idx1; } } return NULL; } };
|