带环链表 & 找出环中入口节点

本文介绍了一种高效的链表环检测算法,通过双指针法判断链表是否存在环,并进一步定位环的入口节点。该算法仅需常数级别的额外空间,时间复杂度为O(n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一个链表,判断它是否有环。

样例

给出 -21->10->4->5, tail connects to node index 1,返回 true

不要使用额外的空间!!

思路:如果一个链表有环, 那么它肯定只有一个环.(一个相交结点)

算法:设两个指针p, q, 初始化指向头.p以步长2的速度向前跑, q的步长是1.这样, 如果链表不存在环, p和q肯定不会相遇.如果存在环, p和q一定会相遇.(就像两个速度不同的汽车在一个环上跑绝对会相遇).复杂度O(n)

代码如下:

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * @param head: The first node of linked list.
     * @return: True if it has a cycle, or false
     */
    bool hasCycle(ListNode *head) {
        // write your code here
        ListNode *p = NULL,*q = NULL;
        for(p = head,q = head;q;q = q->next,p = p->next){
            q = q->next;
            if(!q)break;
            if(p == q)return true;
        }
        return false;
    }
};

问题变形:

找出链表中环的入口结点


还是使用俩指针p和q, q扫描的步长为1, p扫描的步长为2.它们的相遇点为图中meet处(在环上).

假设头指针head到入口点entry之间的距离是K.则当q入环的时候, p已经领先了q为: d = K%n(n为环的周长).

我们设meet处相对entry的距离(沿行进方向)为x, 则有

(n-d)+x = 2x (p行进的路程是q的两倍)

解得x = n-d

那么当p和q在meet处相遇的时候, 从head处再发出一个步长为1的指针r, 可以知道, r和q会在entry处相遇!

算法就是:

初始化三个指针p, q, r全部指向head. 然后p以2的速度行进, q以1的速度行进.当p和q相遇的时候, 发出r指针并以1的速度行进, 当q和r相遇返回这个结点.复杂度O(n)

node_t *find_entry(node_t *head)
{
	node_t *p, *q, *r; 
	
	for (p = q = head; p; p = p->next, q = q->next){
		p = p->next; 
		if (!p) break; 
		if (p == q) break; 
	}
	
	if (!p) return 0; //no ring in list
	
	for (r = head, q = q->next; q != r; r = r->next, q = q->next); 
	
	return r; 
}


给定一个链表,判断它是否有环。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值