给出一个链表;
1.判断其是否带环?
2.如果带环求环的长度?
3.求环的入口节点?
解题思路:
用两个指针,快指针一次走两步,慢指针一次走一步,如果两指针相遇,那么链表带环,若两指针不相遇,则链表不带环。
带环的几种情况:Node* List::find_meet_node(Node* Head)
{
if(Head==NULL)
return NULL;
if(Head->_next ==Head)
return Head;
Node* entry=NULL;
Node* fast=Head;
Node* slow=Head;
while(fast)
{
fast=fast->_next ->_next ;
slow=slow->_next ;
if(fast==slow)
return fast;
}
return NULL;
}
void List::IsHasRing(Node* Head)
{
Node* ret=find_meet_node(Head);
if(ret==NULL)
cout<<"no ring"<<endl;
else
cout<<"have a ring"<<endl;
}
2.求环的长度:
解题思路:
面试题1已经判断过链表带环,且返回两指针相遇节点,求环长度时我们可以让一个指针从相遇节点处开始遍历,当再次回到相遇节点时,它走过的步数就是环的长度。
int List::ring_len(Node* meet)
{
if(meet==NULL)
return 0;
Node* cur=meet->_next ;
int len=1;
while(cur!=meet)
{
cur=cur->_next;
len++;
}
return len;
}
3.求环的入口节点:
方法一:假设上图是一个单链表,两指针走到相遇节点时,慢指针走了L+X步,快指针走了L+X+nC步,(l为环的长度),由于快指针速度是慢指针速度的一倍,那么就有以下的等式:
(L+X)*2=L+X+nC;化解可得:L=nC-X;
那解题时我们可以用两个指针,一个指针从链表的开始位置走,另一个指针从相遇的节点处开始走,也就是y,两个指针相遇的节点就是入口点。
Node* List::find_entry(Node* Head,Node* meet)
{
if(meet==NULL)
return NULL;
Node* prev=Head;
Node* post=meet;
while(prev!=post)
{
prev=prev->_next ;
post=post->_next ;
}
return prev;
}
方法二:将相遇的节点处断开,转化为两条链表相交求交点问题,两个指针meet和Entry分别遍历到链表尾,记录两链表的长度len_l1和len_l2,然后让较长的链表先走len=|len_l1 - len_l2|步,然后两指针一起走,直到两指针相遇,相遇的节点就是链表的交点,即环的入口点。
Node* List::find_entry(Node* Head,Node* meet)
{
pLinkNode Entry = head;
pLinkNode meet = MeetNode->next;
int len_head = 0;
int len_meet = 0;
int len = 0;
while (Entry != MeetNode) //求链表长度
{
len_head++;
Entry = Entry->next;
}
while (meet != MeetNode)//求链表长度
{
len_meet++;
meet = meet->next;
}
Entry = head;
meet = MeetNode->next;
if (len_head > len_meet)
{
len = len_head - len_meet;
while (len--)
{
Entry = Entry->next;
}//较长链表先走len=|len_l1 - len_l2|步
}
else
{
len = len_meet - len_head;
while (len--)
{
meet = meet->next;
}//较长链表先走len=|len_l1 - len_l2|步
}
while (meet != Entry)
{
Entry = Entry->next;
meet = meet->next;
} //两指针同时走,相遇节点就是环入口点
return Entry;
}
测试用例:
void test3()//测试是否带环
{
List l;
Node* node1=new Node(0);
Node* node2=new Node(1);
Node* node3=new Node(2);
Node* node4=new Node(3);
Node* node5=new Node(4);
Node* node6=new Node(5);
Node* node7=new Node(6);
node1->_next =node2;
node2->_next =node3;
node3->_next =node4;
node4->_next =node5;
node5->_next =node6;
node6->_next =node5;
l.IsHasRing(node1);
Node* meet=l.find_meet_node(node1);
cout<<"meet:"<<meet->_data <<endl;
int len=l.ring_len(meet);
cout<<"length:"<<len<<endl;
Node* entry=l.find_entry(node1,meet);
cout<<"entry:"<<entry->_data <<endl;
}
运行结果:
到此结束!