链表面试题3/链表带环问题--判断链表是否带环?

若带环求环的长度?若带环求环的入口点?并计算以上每个问题的时间复杂度
求单链表是否存在环,环长,带环链表长
给定一个单链表,只给出头指针h:
1、如何判断是否存在环?
2、如何知道环的长度?
3、如何找出环的连接点在哪里?
4、带环链表的长度是多少?
解法:
1、对于问题1,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。
2、对于问题2,记录下问题1的碰撞点p,slow、fast从该点开始,再次碰撞所走过的操作数就是环的长度s。
3、问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。以下是个人证明,原博客的证明链接不中用了:
证:设连接点距离头指针为n,到相交点距离为x,圈长p,则2(n+x)=n+x+kp(k>0整数)必存在,转换后n=(k-1)p+(p-x),证明完毕
4、问题3中已经求出连接点距离头指针的长度,加上问题2中求出的环的长度,二者之和就是带环单链表的长度
结点的定义:

typedef int DataType;
typedef struct Node
{

    Node(const  DataType& data)
        : _pNext(NULL)
        , _pPre(NULL)
        , _data(data)
    {}

    Node* _pNext;
    Node* _pPre;
    int _data;
}Node, *pNode;
//1.判断链表是否带环
    pair<pNode, bool> IsHaveCircle(pNode pHead)
    {
        assert(pHead);
        pNode pfast = pHead;
        pNode pslow = pHead;
        while (pfast && pfast->_pNext)
        {
            pfast = pfast ->_pNext->_pNext;
            pslow = pslow ->_pNext;
            if (pfast == pslow)
                return make_pair(pslow, true); //带环
        }
        return make_pair(pfast, false);  //不带环
    }
    //2.若带环求环的长度
    int sizeCircle(pNode pHead)
    {
        assert(pHead);
        if (!IsHaveCircle(pHead).second)
            return 0;
        pNode Node = IsHaveCircle(pHead).first;
        pNode pCur = Node->_pNext;
        int count = 1;
        while (pCur != Node)
        {
            count++;
            pCur = pCur->_pNext;
        }
        return count;
    }
    //3.若带环求环的入口点
    pNode FindCircle(pNode pHead)
    {
        assert(pHead);
        pNode node = IsHaveCircle(pHead).first;
        pNode pCur = pHead;
        while (pCur != node)
        {
            pCur = pCur->_pNext;
            node = node->_pNext;
        }
        return pCur;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值