判断单向链表中是否有环并确定开始位置

    技术2022-06-25  42

        第一个问题,判断单向链表中是否有环。网上搜到的方法,步长法,两个指针p1和p2,分别以步长1和2开始遍历链表,如果p2追上了p1,则说明存在环路。

        p2每次走2步,p1每次走1步,如果没有环路的话,p2肯定会先到达终点,即p2->next=null。

       

        1(h)->2->3(s)->4->...->m->...->n-1->n(e)->3

    假设链表是这样地,环路是从第3个节点开始的。假设p1,p2相遇于m节点。

    p1走的距离=[h,s] + [s,m] + x[s,e] x表示p1走了x圈, x>=0

    p2走的距离=2([h,s] + [s,m] + x[s,e])

     

    p1,p2相遇肯定是在[s,e]这个区间,他们的位移相同,不过p2可能比p1多跑了z圈,z>=1。

    2([h,s] + [s,m] + x[s,e])- ([h,s] + [s,m] + x[s,e]) = z[s,e] 即  [h,s] + [s,m] + x[s,e] =  z[s,e] 即 [h,s] + [s,m] = (z-x)[s,e]。存在使这个等式成立的数,比如 2 + 4 = (1 - 0) * 6。

     

    (可是总觉得哪里不对劲呢?)

     

    [占位待续]

     

     

        还有没有别的方法呢?如果存在环路的话,则有两个节点的next指针,指向同一个地址。指针p从头节点开始遍历,用一个数据结构来记录每个节点的next地址的值,如果p->next=null,走完了整个链表,说明没有环路。否则一定会有某个节点的next值已经被记录过了,这个next指向的节点就是环路的开始。

        现在的问题是,用什么样的数据结构来保存next值,并且可以实现快速查找。因为不知道链表节点的数目,所以这个数据结构要能够动态分配和增长。。。啊,好像又是链表比较合适,原始链表的每个节点的next值,组成一个新的链表,记为LL,并且指针p每移动一步,都需要从头遍历LL,查找是否出现过p->next值。。。哇,好麻烦。。其实我一开始想用hash的,但是这个地址又不是ASCII码。。。。可以先分配固定长度,比如256个元素的数组,然后设计一个hash函数,将p->next值映射到数组,冲突解决嘛,链地址法。。。OMG,也好复杂哦。


    最新回复(0)