题目:见下图
答案:见下图
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode* detectCycle(struct ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
break;
}
}
if (fast==NULL || fast->next==NULL) {
return NULL;
}
ListNode* meet = head;
while (fast!=meet) {
fast = fast->next;
meet = meet->next;
}
return meet;
}
解析:
(1)使用快慢指针找出在链表环中的相交点
采用快慢指针,快慢二倍指针在环形链表中是会相遇,具体可见我的下一篇博客,找出交点再利用head到环形链表的头结点的关系即可进行求解
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
break;
}
}
(2)判断链表是否是环形链表
倘若链表不为环形链表那么走的快的指针便会走到末尾的空指针,反之则为环形链表,环形链表中的指针会在链表中一直走一直循环,不会出现NULL的状况
if (fast==NULL || fast->next==NULL) {
return NULL;
}
(3)找出相遇点
假设链表的总长度为C,头链表到环形链表的交点的距离为L,两个结点相交,慢指针走到路程为X
那么有两种情况
1.head到环形链表的交点的长度小于环形链表的长度,
此时有短指针的路程为(L+X)
长指针的路程为(L+C+X)
由于长指针的路程是短指针的二倍,那么有2(L+X)=(L+X+C)
解的L=C-X,此时我们可以定义一个meet指针=head,让meet指针和fast指针走相同步,那么其相遇点即为环形链表的头节点
2.接下来我们开始讨论第二种情况,即head到环形链表的交点长度大于环形链表的长度,此时快慢指针相遇时快指针已经在环形链表中走了好多圈我们记为N圈,同理
此时有短指针的路程为(L+X)
长指针的路程为(L+N*C+X)
由于长指针的路程是短指针的二倍,那么有2(L+X)=(L+X+N*C)
化简L+X=N*C
L+X=(N-1)*C+C,那么(N-1)*C我们可以认为长指针在链表中绕了整整(N-1)圈,那么我们可以在这里再次化简为L=C-X+(N-1)*C,这里我们可以想象一下有若干个长度为C的环形链表其为(N-1)个,对应快指针的圈数,将其累加起来,定义一个meet指针=head,让meet指针和fast指针走相同步,那么其相遇点即为环形链表的头节点
ListNode* meet = head;
while (fast!=meet) {
fast = fast->next;
meet = meet->next;
}
return meet;
到这里我们解题完毕
如果对您有帮助的话点一个免费的赞和收藏叭!