剑指Offer: 链表中环的入口结点

链表中环的入口结点


一个链表中包含环,请找出该链表的环的入口结点。


方法一:维护一个哈希表
1、哈希容器set。
2、加入元素,通过返回值判断加入失败则是入口结点。
3、注意非环对空指针的判断。
空间复杂度比较大,如果链表很长,这个方法不再合适,但是这是一个思路扩展,显然对于hash,用处有很多。

方法二:两个指针
1、先找汇聚点。
2、找到汇聚点后,fast比slow多跑的距离k*n和slow跑的距离x是相等的。其中n为环结点数。此时slow距汇聚点为t,一个回到起点跑x-t,另一个继续向前跑k*n-t。

方法三:next置空
1、两指针一前一后,pre,cur。
2、后的将next置空,pre->next=nullptr,pre=cur,cur=cur->next。
3、当cur为空的时候,表示此处曾经来过,并且断开了链表。返回pre。
注意:此方法必须有环,或是提前判断。但是破坏了链表,不可取。


/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        //O(1)空间
        if(!pHead)  return nullptr;
        ListNode *slow=pHead,*fast=pHead;
        /*寻找汇聚点此时2*X=X+k*n
        *fast=2X,slow=x,环=n:表示结点个数
        *X =k*n
        *重新开始走,表示将X(k*n)剩余部分走完。
        */
        while(fast){
            if(fast->next)   fast=fast->next->next;
            else return nullptr;
            slow=slow->next;
            if(fast==slow)  break;
        }
        for(slow=pHead;slow!=fast;slow=slow->next,fast=fast->next);
        return slow;
        /*空间复杂度过高
        unordered_set<ListNode*> ps;//可以维护一个容器装地址
        ListNode *cur=pHead;//set插入是有返回状态的!!!
        while(ps.insert(cur).second&&cur!=nullptr){
            cur=cur->next;
        }
        if(!cur)    return nullptr;
        return cur;
        */
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值