链表中环的入口节点

题目描述

给定一个链表,若其中包含环,则输出环的入口节点。

若不包含环,则输出null。

样例

在这里插入图片描述

Input: 如图示链表:1->2->3->4->5->6
Output: 2(下标为2的节点)

解题思路

  • 描述

    用一张图形象地描述该问题(该图来自www.acwing.com):

    假定这是一个带环的链表,a为链表首部节点,b为环的入口节点,c为环中的某一节点。a、b相距x,b、c相距y,圈长度为l。
    使用两个指针first和second分别从a出发,first每次走一步,second每次走两步。
    容易知道,对于带环的链表,first和second一定会在环中的某一节点相聚,假定这一节点就是c。
    假定当first和second相聚时,second在环中已转圈a圈(first并没有转圈0圈,可以通过举例得出该结果)。那么有 2 ( x + y ) = x + a l + y ⇔ x + y = a l 2(x + y) = x + al + y \Leftrightarrow x + y = al 2(x+y)=x+al+yx+y=al
    因此,当first和second相聚时,令first从a开始出发,second从c继续出发,两者每次均走一步,两者再次相聚之处便是b。

  • 实现代码:

    /*
    struct ListNode {
    	int val;
    	struct ListNode* next;
    
    };
    */
    
    ListNode* entryNodeOfLoop(ListNode* head)
    {
    	struct ListNode* i = head, *j = head;
    	while (i && j)
    	{
    		i = i->next;
    		j = j->next;
    		if (j)
    		{
    			j = j->next;
    			if (j == NULL) // j走到链表尾部,证明不存在环
    				return NULL;
    		}
    
    		if (i == j) // 此时相遇
    		{
    			break;
    		}
    	}
    
    	i = head;
    	while (i && j)
    	{
    		i = i->next;
    		j = j->next;
    		if (i == j) // 再次相遇,返回即可
    		{
    			return i;
    		}
    	}
    
    }
    
  • 复杂度分析

    时间复杂度:\approx O(n)≈O(n)

    first指针走 (2x + y) 步,second指针走 (2x + 2y + x ) 步,总共走 (5x + 3y)步。因此基本上是 O(n)

    空间复杂度:\approx O(1)≈O(1)
    使用两个辅助变量first和second。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值