链表是否带环?环长?入口?时间复杂度?

来源:互联网 发布:淘宝网的管理模式分析 编辑:程序博客网 时间:2024/05/16 08:51

【是否带环】

      基本思路:定义两个指针从头结点开始,一个一次向后走一步,一次走两步,循环,若能够走到NULL,则不带环,若走到两个指针相等,则带环。

代码如下:

pair<bool,PNode> HasCircle(PNode phead)//判断是否带环,带环的话环的长度,入口。{assert(phead);                 //时间复杂度是O(n)PNode pcur = phead;PNode prev = pcur;int flag = 0;while (prev&&prev->_pNext){pcur = pcur->_pNext;prev = prev->_pNext->_pNext;if (prev==pcur){return make_pair(true,pcur);}}return make_pair(false,(PNode)NULL);}

【环长】

       基本思路:判断完是否带环后,返回相遇位置,定义两个指针,一个整形count初始化为0,再从相遇位置开始,一个指针一次走一步,一个指针一次走两步,count++, 等到再次相遇时,返回count的值即为环长。

代码如下:

int LenOfCircle(PNode phead)//带环求环的长度 时间复杂度为O(n){pair<bool,PNode> res = HasCircle(phead);if (!res.first){return 0;}PNode pcur = res.second;PNode prev = pcur;int count = 0;while(true){pcur = pcur->_pNext;prev = prev->_pNext->_pNext;count++;if (prev == pcur){return count;}}}

【环的入口】

基本思路:

       第一次相遇时的位置知道后,则从头到入口的距离和相遇点到入口的距离相等(后有具体证明),则可以让一个指针从头开始走,一个指针从相遇点开始走,走到两个指针相遇,则相遇点就是入口点。

证明:(理科生,所以用公式来证明)

        求环长时,相遇点在5的地方,若pcur一步走两个,则pcur的路径为:l+R+h+R(也就是一圈然后在加上R),

prev的路径是:l+R,而这两个指针的路径又是有2倍的关系。

则:l+2R+h = 2*(l+R)

解上面的式子可以得到:l = h,也就是从头到入口的距离和从相遇点到入口的距离相等。


代码如下:

PNode EnterOfCircle(PNode phead)//带环求环的入口点//以及求时间复杂度O(n){pair<bool,PNode> res = HasCircle(phead);if (!res.first){return 0;}PNode pcur = res.second;PNode prev = phead;while (true){pcur = pcur->_pNext;prev = prev ->_pNext;if (prev == pcur){return pcur;}}}



阅读全文
0 0