链表带环问题

1、判断链表是否带环
解析:这里可以用到追及的思维,设置两个快慢指针同时从头结点出发。如果链表带环,则快指针一定会追上满指针。

PNode HasCircle(PNode pHead)// 判断单链表是否带环 
{
    //快慢指针
    PNode pFast = pHead;
    PNode pSlow = pHead;

    while (pFast && pSlow){
        pFast = pFast->pNext->pNext;
        pSlow = pSlow->pNext;
        if (pFast == pSlow)
            return pSlow;
    }
    return NULL;
}

2、求环的长度
解析:判断链表是否带环会得到一个快慢指针相遇的节点,从这个节点开始计数,走一圈就是环的长度。

size_t GetCircleLen(PNode pHead)// 求环的长度
{
    PNode pMeetNode = HasCircle(pHead);
    PNode pCur = NULL;
    size_t len = 0;
    if (pMeetNode == NULL)
        return 0;
    pCur = pMeetNode;
    while (pCur->pNext!= pMeetNode){
        len++;
        pCur = pCur->pNext;
    }
    return len;
}

3、求环的入口点
链表带环问题_第1张图片
如上图(y为环的周长):快慢指针走的时间相同,快指针走的路径是满指针的二倍,可得到
F = 2S
S=x+d
F=2 ( x + d ) = x + d + ny
得到:x = ny - d = (n-1)y + (y - d)(即表示从头结点到入口点和相遇点到入口点的距离一样)


PNode GetEnterNode(PNode pHead, PNode pMeetNode)// 求环的入口点 
{
    PNode pH = pHead;
    PNode pM = pMeetNode;
    if (pH == NULL || pM == NULL)
        return NULL;
    //到这步说明链表一定有环
    while (pH != pM){
        pH = pH->pNext;
        pM = pM->pNext;
    }
    return pM;
}

4、判断两链表是否相交(假设链表不带环)
解析:仔细分析链表相交的情况,我们可以看到两链表最后的节点一定是相同的,否则它们就不想交。在这里直接遍历到尾结点,判断它们的尾结点是否相同。

//判断两个不带环链表是否相交(假设链表不带环)
int IsCrossWithoutCircle(PNode pHead1, PNode pHead2)
{
    PNode pTail1 = pHead1;
    PNode pTail2 = pHead2;

    while (pTail1)
        pTail1 = pTail1->pNext;

    while (pTail2)
        pTail2 = pTail2->pNext;

    return pTail1 == pTail2;
}

我在一些书上还看到另一种方法:把链表一的尾结点跟链表二的头结点链接起来构成环,若两链表相交则构成环。这样判断相交就变成了判断是否带环,求交点就变成了求环的入口点。

5、求交点


PNode GetCorssNode(PNode pHead1, PNode pHead2)//若相交求交点
{
    size_t size1 = 0;
    size_t size2 = 0;
    PNode pCur1 = pHead1;
    PNode pCur2 = pHead2;
    int div = 0;

    if (NULL == pHead1 || NULL == pHead2)
        return NULL;

    if (!IsCrossWithoutCircle(pHead1, pHead2))//不带环链表不相交
        return 0;

    while (pCur1)
    {
        size1++;
        pCur1 = pCur1->pNext;
    }

    while (pCur2)
    {
        size2++;
        pCur2 = pCur1->pNext;
    }

    div = size1 - size2;
    if (div > 0)
    {
        while (div--)
            pCur1 = pCur1->pNext;
    }
    else
    {
        while (div++)
            pCur2 = pCur2->pNext;
    }

    while (pCur1 != pCur2)
    {
        pCur1 = pCur1->pNext;
        pCur2 = pCur2->pNext;
    }
    return pCur1;
}

你可能感兴趣的