每日一题——链表中环的入口

每日一题

链表中环的入口节点

题目链接

每日一题——链表中环的入口_第1张图片

思路(双指针法)

  • 第一步:第一步当然是判断该链表是否存在环。由昨天的题目判断链表是否有环,可以很简单的进行判断
  • 第二步:即找到环的入口节点。
    • 我们可以在第一步中可以得到快慢指针相遇的节点位置,可以设相遇节点到头节点的距离为X,环入口节点到相遇节点的距离为Y(从左到右),相遇节点到环入口节点的距离为Z(从右到左),如此图中,X = 2, Y = 2, Z = 2
    • 如图:每日一题——链表中环的入口_第2张图片
  • 由分析可得:当快慢指针相遇时,慢指针slow一共走了X + m(Y + Z) + Y个节点,快指针fast一共走了X + n(Y + Z) + Y个节点,我们预定快指针fast每次比慢指针slow多走一个节点,则X + n(Y + Z) + Y = 2(X + m(Y + Z) + Y),即X + Y = (n - 2m)(Y + Z),即X = (n - 2m - 1)(Y + Z) + Z。
  • 我们可以再定义连个指针index1,index2,令index1指向链表头,index2指向快慢指针相遇的节点,并每次让index1,index2每次一起走一个节点,由X = (n - 2m - 1)(Y + Z) + Z可知,index1走到环入口节点所走过的节点数恰好等于index2走到环入口节点所走过的节点数加上整数倍环的节点数,即当index1与index2相遇的点即为环的入口节点。

实现代码

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param pHead ListNode类 
 * @return ListNode类
 */
struct ListNode * Judge_Loop(struct ListNode *pHead) 	//判断链表是否有环的函数,如果没有,则返回NULL,如果有,则返回相遇的节点
{
    if(!pHead)
        return NULL;
    struct ListNode*fast,*slow;
    fast = slow = pHead;
    while(slow && fast)
    {
        slow = slow->next;
        if(!fast->next)
            return NULL;
        fast = fast->next->next;
        if(fast == slow)
            return fast;
    }
    return NULL;
}
struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
    if(!Judge_Loop(pHead))		//如果链表没有环,则直接返回NULL
        return NULL;
    struct ListNode* index1 = pHead;		//令index1指向表头
    struct ListNode* index2 = Judge_Loop(pHead);		//令index2指向相遇节点
    while(1)
    {
        if(index1 == index2)	//当index1和index2再次相遇时,相遇位置即为环的入口
            return index1;
        index1 = index1->next;		//index1,index2每次下滑一个位置
        index2 = index2->next;
    }
}

你可能感兴趣的:(每日一题,#,链表相关,链表,数据结构,c++,算法,c语言)