• 确定链表环的长度与入口,以及算法的正确性分析


    在之前的文章里偶分析了追赶法判断链表是否有环(叫龟兔赛跑法可能会更贴切)算法的正确性。但是还有几个问题必须解决:
    1. 环的长度
    2. 环的入口

    3.整个链表的长度
    第一个问题很好解决,因为龟兔二人第一次相遇的点(不放设为k)必然在环内,这时再以相遇点作为起点,新定义一向量向前移动,直到移动到自身为止,移动的步数就是环的长度,这个很好理解。
    第二个问题稍微要思考一下,如果使用标记法,这个问题很好解决,但是在追赶法中我们需要看看这个入口位置和相遇点k有什麽关系。
    给出带头的单链如下所示:
    H->1->2->3->4->5->6->7-8->9
    长度n=9
    环的入口点设在a=6处
    很明显环的长度就是n-a+1
    则由相遇的步数公式k=d*(n-a+1)直到第一个k=8
    我们发现从k处走到a处的步数y符合公式y=d2*(n-a+1)+(n-k+1)的形式,其中d2是正整数(>=0),这个很好理解,要麽d2=0,从8走到9再走到6就是3步=n-k+1,或者d2>0,再多走一圈。
    而k=d*(n-a+1),由此代入上式得:y=(d2-d)(n-a+1)+n+1;
    令d2-d=-1,则y=a;这是神麽意思涅?没错,这意味着只要令d2比d小1,这时候从k走到a的步数恰好就等于a在链表中所处的位置,也即使从链表头走到a的步数。
    所以我们用两个游标(指针)就可以完成环入口点的挖掘,一个游标从链表头移动,一个游标从k移动,它们两移动了a步之后恰好在a位置相遇!

    第三个问题呢:

    基于前两个问题,这个问题再简单不过了,n-a+1环的长度我们已知了,a环的入口点我们已知了,n还能不知嘛?
    话不多说,给出代码(不含第三个问题):

       1:  /*
       2:  check if have loop, and caculate the step to find the loop, the length of loop, the entry point of loop
       3:  */
       4:  int check_loop3(pnode list,int *stepCount,int *lengthOfLoop,int *startIndexOfLoop)
       5:  {
       6:      pnode p1=list;
       7:      pnode p2=list;
       8:      if(p1==p2->next)
       9:      {
      10:          *stepCount=1;
      11:          *lengthOfLoop=1;
      12:          *startIndexOfLoop=0;
      13:          return 1;
      14:      }
      15:   
      16:      while(p1->next!=NULL && p2->next!=NULL)
      17:      {
      18:          (*stepCount)++;
      19:          p1=p1->next;
      20:          p2=p2->next->next;
      21:          if(p1==p2)
      22:          {
      23:              *lengthOfLoop=get_loop_length(p1);
      24:              *startIndexOfLoop=get_startindex_of_loop(list,p1);
      25:              return 1;
      26:          }
      27:      }
      28:   
      29:   
      30:      //if not fount, reset the count
      31:      stepCount=0;
      32:      lengthOfLoop=0;
      33:      startIndexOfLoop=0;
      34:      return 0;
      35:  }
      36:   
      37:  /*
      38:  find the entry point of loop
      39:  assume the loop already exist
      40:  */
      41:  int get_startindex_of_loop(pnode list,pnode thek)
      42:  {
      43:      int index=0;
      44:      pnode p1=list;
      45:      pnode p2=thek;
      46:   
      47:      while(p1!=NULL && p2!=NULL)
      48:      {
      49:          if(p1==p2)
      50:          {
      51:              return index;
      52:          }
      53:          p1=p1->next;
      54:          p2=p2->next;
      55:          index++;
      56:      }
      57:   
      58:      return -1;
      59:  }
      60:   
      61:  /*
      62:  find the loop length
      63:  assume the loop already exist,or will never stop loop
      64:  */
      65:  int get_loop_length(pnode thek)
      66:  {
      67:      int len=0;
      68:      pnode p=thek->next;
      69:      len++;
      70:      while(p!=thek)
      71:      {
      72:          p=p->next;
      73:          len++;
      74:      }
      75:      return len;
      76:  }

    TEST:

       1:   
       2:  int main()
       3:  {
       4:      int i=0;
       5:      pnode list=create_newnode();
       6:      pnode p;
       7:      for(i=1;i<10;i++)
       8:      {
       9:          p=create_newnode();
      10:          p->value=i;
      11:          append(list,p);
      12:      }
      13:      p->next=list->next->next->next->next->next->next;
      14:      //list->next->next=list;
      15:      //list->next->next=list;
      16:   
      17:      int x=0;
      18:      int y=0;
      19:      int z=0;
      20:      int r=check_loop3(list,&x,&y,&z);
      21:   
      22:      printf("%d,%d,%d,%d",r,x,y,z);
      23:      return 0;
      24:  }
  • 相关阅读:
    stylus使用文档总结:选择器+变量+插值+运算符+混合书写+方法
    vue项目配置使用flow类型检查
    项目中存在的问题
    坚持
    Enum枚举类使用集合
    JS 随机数字抽签
    【转】Basic C# OOP Concept
    EF异常:WebForm、Console、Winform层不引入EF报错
    EF异常:“System.InvalidOperationException”类型的未经处理的异常在 mscorlib.dll 中发生
    WebServices中使用Session
  • 原文地址:https://www.cnblogs.com/dancewithautomation/p/2580444.html
Copyright © 2020-2023  润新知