1.环形链表1
看题:. - 力扣(LeetCode)
思路1:哈希表
遍历所有节点,每次遍历一个节点时,判断该节点是否被访问过。
可以使用哈希表来存储所有已经访问过的节点。每次到达一个节点,如果该节点已经存在于哈希表中,则说明该链表是环形链表,否则就将该节点加入哈希表中。重复这一过程,直到我们遍历完整个链表。
思路2:快慢指针
创建两个指针,一个快指针一个慢指针,快指针一次走两步,慢指针一次走一步,如果是环形链表则两个指针会相遇,所以每走一次判断两个指针是否相等。如果不是环形链表则快指针会走到NULL。
1.1.快慢指针
看图:
代码实现:
bool hasCycle(struct ListNode *head) {struct ListNode *fast=head;struct ListNode *slow=head;while(fast&&fast->next){fast=fast->next->next;slow=slow->next;if(fast==slow){return true;}}return false;
}
2.环形链表2
看题:. - 力扣(LeetCode)
目录
1.环形链表1
1.1.快慢指针
2.环形链表2
思路1:快慢指针
先上结论:下面是一个环形链表,node结点位是快慢指针相遇的位置结点,phead是入环结点。
其中L的长度等于M的长度,知道这个结论后代码就信手拈来了。
下面是证明L=M:
如果是环形链表那么两个指针会相遇,找到相遇的节点node:
那么如图设置:head到入环的结点的长度为L,入环到相遇的结点node的长度为N,环的长度为C:
那么开始遍历链表,当然慢指针slow入环时快指针已经在环里走了至少一圈,假设为x圈,
当快慢指针相遇时,慢指针在环里面走的长度就是N,因为快指针的相对于慢指针的速度为1,所以每走一步快指针就与慢指针的距离-1,直到相遇。
此时
快指针走的路程:L+N+x*C
慢指针走的路程:L+N
因为快指针的速度是慢指针的两倍,所以路程也是慢指针的两倍。
所以:
L+N+x*C=2*(L+N)
整理一下:
L=x*C-N
处理:
L=(x-1)*C+C-N
式中当x取最小值时:L=C-N
而黑色部分长度就是C-N
此时让head遍历链表,node也开始往下走,当x取的值不是1时,node结点会一直在环里遍历,最终head和node一定会在入环结点相遇。
2.1代码
struct ListNode *detectCycle(struct ListNode *head) {struct ListNode *slow=head;struct ListNode *fast=head;struct ListNode *node=head;while(fast&&fast->next){fast=fast->next->next;slow=slow->next;if(fast==fast)break;}if(fast==NULL||fast->next==NULL)return NULL;while(fast!=node){fast=fast->next;node=node->next;}return fast;
}