判断两个链表是否相交(考虑带环与不带环)
2017-07-17 00:50
288 查看
1.不考虑带环的情况,若相交,求交点
解法一:如果两个链表都无环,则可以把第二个链表接在第一个链表后面,如果得到的链表有环,则说明这两个链表相交。这里如果有环,则第二个链表的表头一定在环上,只需要从第二个链表开始遍历,看是否会回到起点即可判断。假设两个链表长度分别为m和n,则时间复杂度为O(m+n)解法二:若两个链表都无环且交于一点,那么最后一个节点一定是共有的。可以先遍历第一个链表,记录最后一个节点,再遍历第二个链表,将其最后一个节点与第一个链表的最后一个节点比较,若相同,则相交。时间复杂度也为O(m+n)。
代码如下:(结点的结构体)
typedef int DataType; //结点的结构体 typedef struct LinkNode { DataType data; LinkNode* next; }Node,*pNode;
bool IsCrossLink(pNode pHead1, pNode pHead2) //判断两链表是否相交(假设链表不带环) { if (pHead1==NULL || pHead2==NULL) return false; pNode pH1 = pHead1; pNode pH2 = pHead2; while (pH1->next != NULL) pH1 = pH1->next; while (pH2->next != NULL) pH2 = pH2->next; if(pH1 == pH2) return true; else return false; }
扩展问题:
求两个链表相交的第一个节点。
int Size(pNode pHead)//链表有效元素的个数 { int count = 0; pNode pCur = pHead; while (pCur != NULL) { count++; pCur = pCur->next; } return count; } pNode GerCrossNode(pNode pHead1, pNode pHead2) //获得相交结点 { if (!IsCrossLink(pHead1,pHead2))//不相交,直接返回 return NULL; pNode pH1 = pHead1; //指向第一个链表 pNode pH2 = pHead2; //指向第二个链表 int size1 = Size(pHead1); //第一个链表长度 int size2 = Size(pHead2); //第二个链表长度 int steps = size2 - size1; if (steps > 0) //使两个指针到交点的相同 { while (steps--) pH2 = pHead2->next; } else { while (steps++) pH1 = pHead1->next; } while (pH1 != pH2) { pH1 = pH1->next; pH2 = pH2->next; } return pH1; }
2.考虑是否带环
首先要判断有头指针的单链表是否有环。解法:使用追逐的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如果存在环,则两者相遇;如果不存在环,fast遇到NULL退出。
pNode IsRoundLink(pNode pHead) //判断链表是否带环 { if (pHead == NULL) return NULL; pNode pFast = pHead; pNode pSlow = pHead; while (pFast != NULL && pFast->next != NULL) { pFast = pFast->next->next; pSlow = pSlow->next; if (pFast == pSlow) { return pFast; } } return NULL; }
若两个都无环,回到第一种情况;
若一个有环,一个无环,不用判断,两链表肯定不相交;
若两个都有环,判断第一个链表的碰撞点(fast与slow相遇的节点,这里是为了方便判断是否带环的函数若带环将碰撞点传回来)是否出现在第二个链表的环中,如果在,则相交。(相交时,环必定是两链表共有的。)
寻找带环单链表的环入口节点的方法:
碰撞点到交点的距离=头指针到交点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是交点。
pNode GetEnterNode(pNode pHead, pNode pMeet) // 获得环的入口点 { if (pMeet == NULL || pHead == NULL) return NULL; pNode pH = pHead; while (pH != pMeet) { pH = pH->next; pMeet = pMeet->next; } return pMeet; }
若有环,计算出两链表的长度len1、len2(环的长度与环的头指针到交点长度之和就是链表长度)。
如果len1>len2,则第一个链表的指针先走len1-len2,然后第二个链表的指针开始走,两者相遇的点就是相交点;
如果len2>len1,则第二个链表的指针先走len2-len1,然后第一个链表的指针开始走,两者相遇的点就是相交点。
求环的长度的方法:
让指针从碰撞点开始走,再次碰撞所走过的操作数就是环的长度。
int CircleLen(pNode pMeet) //获得环的长度 { int length = 1; if (pMeet == NULL) return -1; pNode pCur = pMeet->next; while (pCur != pMeet) { pCur = pCur->next; length++; } return length; }
相关文章推荐
- 判断两个链表是否相交,若相交,求交点,考虑带环情况实现代码
- 判断两个链表是否相交,若相交,求交点。(假设链表带环、不带环)
- 判断两个链表是否相交,若相交,求交点,若带环呢/fork继承问题
- ]数据结构:单链表之判断两个链表是否相交及求交点(带环、不带环)
- 判断两个链表是否相交,若相交,求交点:1.不带环。2.有可能带环
- 链表--1.判断两个链表是否相交,若相交,求交点。(假设链表不带环)2.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)
- 链表面试题(十二)---判断两个都不带环的链表是否相交
- 如何判断两个链表是否相交。(假设链表带环、不带环)
- 判断两个不带环链表是否相交?若相交,求入口点。
- 判断两个链表是否相交?若相交,求交点(假设链表带环)
- 面试题----判断两个链表是否相交(可能带环)
- 判断两个带环链表是否相交,并求出第一个相交点
- 判断两个链表是否相交,若相交,求交点。(假设链表可能带环)
- 每日一刷——1.判断两个链表是否相交,若相交求交点(链表不带环&带环)2.fork()问题
- 判断两个链表是否相交,若相交,求交点。(假设链表不带环)(C语言)
- 1.判断两个链表是否相交,若相交,求交点。(假设链表不带环)2.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
- 判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】(C语言)
- 判断两个链表是否相交
- 判断单链表是否存在环,判断两个链表是否相交问题详解(转载)
- 题目:①判断一个单向链表是否有环,如果有环则找到环的入口节点。 ②判断两个单向链表是否相交,如果相交则找到交点节点。