http://blog.youkuaiyun.com/xie376450483/archive/2011/03/13/6247071.aspx
今天要讲的和那篇类似,就是给定两个链表,如何来判断这两个链表相交了
首先应该分两种情况考虑,第一:这两个链表本身都没有环。 第二:这两个链表本身都有环
首先讲都没有环的情况,如下图
方法很多,不过我想最简单的方法是遍历第一个链表,然后遍历到最后一个节点时候,用一个指针把节点地址记录下来
然后再来遍历第二个链表,同样记录下最后一个链表的地址,如果两个指针的指向一样,那么就可以判断出两个链表相交了
然后再来判断他们的交点
把第一个链表的尾节点指向第二个链表的头结点,这样就形成了一个6字型的环链表,利用我们前面那篇文章讲的方法就可以求出相交节点
然后说第二种情况
两个链表本身都有环,首先我们应该知道如果一个链表有环,一个链表没有环,那么他们肯定不想交,自己画画图就明白了,不多说
现在判断出两个链表都有环,那么怎么来判断相交了呢?
方法是遍历利用前面的方法找到第一个链表的环点,然后将环断开(当然不要忘记了保存它的下一个节点),然后再来遍历第二个链表,如果发现第二个链表从有环变成了无环,那么他们就是相交的嘛,否则就是不相交的了。
在判断出来两个有环的链表有交点后,然后来找出相交的节点,这时候又分了两种情况,相交点在环之前还是相交点在环之后,这样讲不严谨,应该是对一个链表来讲相交点是在另一个链表的环之前还是之后。
方法如下
首先找到两个链表的环点,利用前面那篇文章的方法,假设两个链表的环点分别是p1,p2 加入p1==p2 说明相交点是在环点之前,
如下图:
这时候我们可以从环点断开,同样记得保存下一个节点,然后把环点指向其中一个链表的表头,这样就把问题转换成前面6字形环形链表的相交节点问题
如果两个链表的相交情况如下图呢?
那这样就很那说哪个是交点了,因为有两个交点,其实不叫两个交点,是相对于l1来讲交点是l2的环点,相对于l2来讲交点是l1的环点
而环点同样是前面的方法得到的。
template<typename T>
ListNode<T>* FindFirstCommonNode_2(ListNode<T>* pHead1, ListNode<T>* pHead2)
{
ListNode<T>* pEntrance1 = FindRingEntrance(pHead1);
ListNode<T>* pEntrance2 = FindRingEntrance(pHead2);
ListNode<T>* pResult = NULL;
if(pEntrance1 == pEntrance2)
{
ListNode<T>* pTemp1 = NULL, *pTemp2 = NULL;
if(pEntrance1)
{
// 环入口点已经相交,寻找第一交点。
pTemp1 = pEntrance1->pNext;
pTemp2 = pEntrance2->pNext;
pEntrance1->pNext = NULL;//断裂后变成两个单链表的方法来计算
pEntrance2->pNext = NULL;
pResult = FindFirstCommonNode(pHead1, pHead2);
pEntrance1->pNext = pTemp1;
pEntrance2->pNext = pTemp2;
}
else
{
// 无环单链表求第一交点
pResult = FindFirstCommonNode(pHead1, pHead2);
}
return pResult;
}
else if(pEntrance1 == NULL || pEntrance2 == NULL)
{
// 一有环,另一个无环,无交点
return NULL;
}
else
{
// 入口点不同的两环求交点
pResult = pEntrance1->pNext;
while(pResult != pEntrance2 && pResult != pEntrance1)
{
pResult = pResult->pNext;
}
return pResult == pEntrance2 ? pResult : NULL; //不确定两个环链表是否相交,否则两个环结点任一个都是结果
}
}