剑指offer 56-链表中环的入口点

来源:互联网 发布:mac口红代购价 编辑:程序博客网 时间:2024/05/17 07:06

首先判断链表中是否包含环

         用到了一快(每次走两步)一慢两个指针,如果两个指针相遇,表明链表中存在环。两个指针相遇的节点一定是在环中。

         可以从这个节点触发,一边继续向前移动一边计数,当再次回到这个节点时,就可以得到环中节点数nodesLoop了。

然后找到入口点

         指针p1和p2在初始化指向链表的头结点,指针先在链表中移动nodesLoop步,接下来两个指针已相同的速度向前移动,直到它们相遇,相遇的节点正好是环的入口节点。      


#include <iostream>using namespace std;struct ListNode{int nValue;ListNode *nNext;};ListNode * createListNode( int a[],int length){   if(length == 0 )return NULL;   ListNode *head = NULL;   ListNode *rear = head;   for(int i=0;i<length;i++)   {   ListNode *tmp =new ListNode[sizeof(ListNode)];   tmp->nValue = a[i];   if(rear == NULL)        head = tmp;   else   rear->nNext = tmp;        tmp->nNext = NULL;         rear =tmp;   }    rear->nNext = head->nNext->nNext;  return head;}ListNode *MeeingListNode(ListNode *head)  //找到相遇点{if(head == NULL)return NULL;ListNode *pSlow =head;ListNode *pFast = pSlow->nNext ;while( pSlow !=NULL  && pFast != NULL){if(pSlow == pFast )        return pSlow;pSlow = pSlow->nNext;pFast = pFast ->nNext;if(pFast != NULL)pFast = pFast ->nNext;}return NULL;}void printListNode(ListNode *head){for(int i=0;i<8;i++){cout<<head->nValue<<" ";head = head->nNext;}cout<<endl;}ListNode *EnterNodeOfLoop(ListNode *head)     //找到入口点{ListNode *meetingNode = MeeingListNode(head);if(meetingNode == NULL)return NULL;int nodesLoop =1;   //易出错点ListNode  *pNode= meetingNode ;while( pNode->nNext != meetingNode)   {   pNode= pNode->nNext;   nodesLoop++;}ListNode *pFast = head, *pSlow =head;for(int i=0;i<nodesLoop;i++)    pFast = pFast->nNext;while( pSlow != pFast){pSlow = pSlow->nNext;    pFast = pFast ->nNext;}   return pSlow;}void main(){ListNode *head = NULL,  *startNode = NULL;int a[] ={1,2,3,4,5,6,7};head = createListNode(a ,sizeof(a)/sizeof(int));printListNode(head);    startNode = EnterNodeOfLoop( head );//startNode = EnterNodeOfLoop( NULL );if(startNode !=NULL)   cout<<startNode->nValue<<endl;}


0 0