您的位置:首页 > 职场人生

链表常见面试题三:解决链表带环问题

2016-04-11 20:04 731 查看
问题1:判断链表是否带环

解题思路:

用两个指针,快指针一次走两步,慢指针一次走一步,如果两指针相遇,那么链表带环,若两指针不相遇,则链表不带环。

pLinkNode CheckCycle(pList head)
{
pLinkNode fast = head;
pLinkNode slow = head;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
return slow;   两指针相遇,链表带环,返回相遇点
}
}
return NULL; //若两指针不相遇,返回null,链表不带环
}

问题2:若链表带环则求环的长度

解题思路:

面试题1已经判断过链表带环,且返回两指针相遇节点,求环长度时我们可以让一个指针从相遇节点处开始遍历,当再次回到相遇节点时,它走过的步数就是环的长度。

int GetCircleLength(pLinkNode meet)
{
pLinkNode cur = meet;
int count = 0;
do
{
cur = cur->next;
count++;
} while (cur != meet);
return count;
}

问题3:获取环入口点

解题思路:





方法一:假设上图是一个单链表,两指针走到相遇节点时,慢指针走了x+y步,快指针走了x+y+nl步,(l为环的长度),由于快指针速度是慢指针速度的一倍,那么就有以下的等式:

(x+y)*2=x+y+nl;

化解可得:

x=nl-y;

那解题时我们可以用两个指针,一个指针从链表的开始位置走,另一个指针从相遇的节点处开始走,也就是y,两个指针相遇的节点就是入口点。

pLinkNode GetCycleEntryNode(pList head, pLinkNode MeetNode)
{
pLinkNode Entry= head;
pLinkNode meet = MeetNode;
while (meet != Entry)
{
Entry = Entry->next;
meet = meet->next;
}
return Entry;
}

方法二:





将相遇的节点处断开,转化为两条链表相交求交点问题,两个指针meet和Entry分别遍历到链表尾,记录两链表的长度len_l1和len_l2,然后让较长的链表先走len=|len_l1 - len_l2|步,然后两指针一起走,直到两指针相遇,相遇的节点就是链表的交点,即环的入口点。

pLinkNode _GetCycleEntryNode(pList head, pLinkNode MeetNode)//链表带环转化为链表相交问题获取入口

{
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: