7.剑指offer-链表中环的入口节点

本文介绍两种高效算法来寻找链表中环的入口节点。方法一是使用集合记录已访问节点,方法二是利用快慢指针计算环长并确定入口。文章通过具体代码实现展示了这两种算法的具体操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.题目

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

2.基本思路

设链表中有m个节点

方法1:

  • 遍历链表,将访问过的节点存储在一个表中,边访问边查询,如果访问的节点已经在表中出现,则为环的入口节点
  • 时间复杂度O(m) ,空间复杂度O(m)

方法2:

  • 首选计算环的长度,假设环的长度为n
    • 用快慢指针,慢指针一次走一步;快指针一次走两步, 则快指针速度比慢指针快一倍。无论在环中走多少次,快指针总能追上慢指针
  • 其次,一快一慢指针,快指针的开始位置比慢指针快n步,慢指针从表头开始。当两个指针相等的时候,则为环的入口

3.代码

  • 方法1

      ListNode* EntryNodeOfLoop(ListNode* pHead)
      {
        if(pHead==NULL)
              return NULL;
          set<ListNode*> s;
          ListNode *p=pHead;
          ListNode *res=NULL;
          while(p!=NULL){ // 如果无环,尾指针肯定指向NULL
              if(s.find(p)!=s.end()){
                  res=p;
                  break;
              }else{
                  s.insert(p);
              }
              p=p->next;
          }
          return res;
      }
  • 方法2

      int calCirclelength(ListNode *pHead){
          int res=0;
          if(pHead==NULL || pHead->next==NULL)
              return res;
          ListNode *pLow,*pHigh;
          pLow=pHead;
          pHigh=pHead->next;
          while(pLow!=NULL && pHigh!=NULL && pLow!=pHigh){
              pLow=pLow->next;
              if(pHigh->next)
                  pHigh=pHigh->next->next;
    
          }
          if(pHigh->next==NULL){
            return res;
          }
    
          pHigh=pLow->next;
          ++res;
          while(pHigh!=pLow){
              ++res;
              pHigh=pHigh->next;
          }
          return res;
      }
    
      ListNode* EntryNodeOfLoop(ListNode* pHead)
      {
        if(pHead==NULL)
              return NULL;
          int num=calCirclelength(pHead); // 如果num计算错误,则有可能陷入死循环之中,代码果然是多一行就多一个潜在bug的危险
          if(num==0)
              return NULL;
          ListNode *p,*p1;
          p=pHead;
          int i=0;
    
          while( i < num){
              p=p->next;
              ++i;
          }
    
          p1=pHead;
          while(p1!=p){
              p1=p1->next;
              p=p->next;
          }
          return p;
      }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值