转:有环链表交点判断
http://blog.csdn.net/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; //不确定两个环链表是否相交,否则两个环结点任一个都是结果
- }
- }