判断单链表是否带环?若带环,求环的长度?求环的入口点

问题描述:

判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法的时间复 杂度&空间复杂度。
1、判断单链表是否带环:
实现思路:设置两个快慢指针分别指向链表的头节点,快指针一次走两步,慢指针一次走一步,如果两个相遇了,则单链表带环,如果快指针走到NULL节点,则链表不带环;
代码实现如下:

pSListNode IsCircleList(pSListNode pHead)
{
    pSListNode fast = pHead; //快指针
    pSListNode slow = pHead; //慢指针
    if (pHead == NULL)
    {
        return NULL;
    }
    while (fast&&fast->_next)
    {       
        slow = slow->_next;
        fast = fast->_next->_next;
        if (fast == slow)
        {
            return fast;
        }
    }
    return NULL;
}

2、如果单链表带环,求环的长度:
实现思路:在判断单链表是否带环的问题中,我们找到了单环单链表的相遇结点,用于个指针从单链表的相遇结点开始走,并且设置一个计数器,每走一步,计数器加一,直到该指针再次遇到相遇点,则返回计数器的数;
实现代码如下:

int CircleListLength(pSListNode pos)
{
    pSListNode fast = pos;
    pSListNode slow = pos;
    int count = 0;
    while (1)
    {
        slow = slow->_next;
        fast = fast->_next->_next;
        count++;
        if (fast == slow)
            break;
    }
    return count;
}

3、求带环长度的入口点:
实现思路:
求环的入口点
设环的长度为:C
从链表头结点到入口节点的长度为:L
入口节点到相遇节点的长度为:X
快指针在环中走的圈数:n
快指针走的步数是:L+nC+X
慢指针走的步数是:L+X
根据快指针走的步数是慢指针的两倍可得关系:L+nC+X = 2(L+X) 化简后可得:nC = L+X
结论:从链表头结点到入口节点的长度 = 相遇节点到入口节点的长度
具体代码实现如下:

pSListNode FindCircleEnter(pSListNode pHead, pSListNode pos)
{
    pSListNode cur = pHead;
    pSListNode tmp = pos;
    assert(pos);
    if (pHead == NULL)
        return NULL;
    while (cur != tmp)
    {
        cur = cur->_next;
        tmp = tmp->_next;
    }
    return cur;
}

单链表的问题,同样也可以转换成两个单链表相交的问题,将单环单链表从相遇点断开,然后求其长度,长的先走。具体实现详见:判断两个不带环的链表是否相交,若相交,求交点

猜你喜欢

转载自blog.csdn.net/zl_8577/article/details/81052572