C语言实现单链表面试题--进阶(带环问题)
来源:互联网 发布:网络的拓扑结构 编辑:程序博客网 时间:2024/06/06 05:33
1.判断单链表是否带环?若带环,求环的长度?求环的入口点?
2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
3.判断入口点
2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
函数如下:
typedef int DataType;typedef struct ListNode{DataType data;ListNode* next;}ListNode;
int GetCycleLen(ListNode* plist);//求环长度(若无环则返回0)ListNode* IsCycle(ListNode* plist);//求带环单链表快慢指针相遇点(无环返回NULL)ListNode* GetCycleEntry(ListNode* plist);//求带环单链表入口点(无环返回NULL)ListNode* IsCrossNoCycle(ListNode* plist1, ListNode* plist2);//判断2个无环链表是否相交ListNode* IsCross(ListNode* plist1, ListNode* plist2);//判定2个链表是否相交(分类讨论)
1.判断是否带环
思路:快慢指针,若能相遇则带环
ListNode* IsCycle(ListNode* plist){ListNode* fast = plist, *slow = plist; //注意这种定义形式while(fast && fast->next){fast = fast->next->next;slow = slow->next;if(fast == slow){return slow;}}return NULL;}
思路:从快慢指针相遇点走一圈,用计数器计数
int GetCycleLen(ListNode* plist){//先判断是否为带环单链表,不是的话返回0ListNode* meet = IsCycle(plist);if(meet){int count = 1;ListNode* cur = meet->next;while(meet != cur){cur = cur->next;count++;}return count;}//若meet为空(没有环),返回0else{return 0;}}
3.判断入口点
思路:设头结点到入口点距离L,入口点到相遇点距离X,环长度C
因为快指针是慢指针的两倍,且在相遇点相遇,所以 2(L+X) = L+X+C*n(快指针领先圈数)
解得L=n*C-X
所以从快慢指针相遇点和头结点一起走,他们的相遇点就是入口点
ListNode* GetCycleEntry(ListNode* plist){ListNode* meet = IsCycle(plist);if(meet){while (meet != plist){meet = meet->next;plist = plist->next;}return plist;}else{return NULL;}}
思路:计算两个链表的长度差的绝对值gab,长的链表先移动gab步,然后两个链表一起走。如果在走到结尾之前相遇了,则该相遇点就是交点
ListNode* IsCrossNoCycle(ListNode* plist1, ListNode* plist2){//plist1和plist2都是无环链表则进入循环,且plist1和plist2不为空if(IsCycle(plist1) == NULL && IsCycle(plist2) == NULL && plist1 && plist2){ListNode* cur1 = plist1, *cur2 = plist2;//求plist1和plist2的长度int len1 = 0;int len2 = 0;while (cur1){len1++;cur1 = cur1->next;}while (cur2){len2++;cur2 = cur2->next;}//移动较长的链表的指针,让他和短的链表一样长int gap = abs(len1 - len2);if (len1 > len2){while(gap--){plist1 = plist1->next;}}else{while(gap--){plist2 = plist2->next;}}//一起走,如果中途相等了则有交点while (plist1){if(plist1 == plist2){return plist1;}plist1 = plist1->next;plist2 = plist2->next;}}return NULL;}
1) 两个都不带环;
2) 其中一个带环;
3) 两个都带环
ListNode* IsCross(ListNode* plist1, ListNode* plist2){ListNode* ent1 = GetCycleEntry(plist1);ListNode* ent2 = GetCycleEntry(plist2);//1.两个都不带环,转化成无环相交问题if (ent1 == NULL && ent2 == NULL){return IsCrossNoCycle(plist1, plist2);}//2.其中一个带环,必定不相交else if ((ent1 == NULL && ent2) || (ent2 == NULL && ent1)){return NULL;}//3.两个都带环//1)不相交//2)尾交//3)环交else{//1)若入口点相同则尾交,去掉环,转化成无环相交问题if(ent1 == ent2){ent1->next = NULL;return IsCrossNoCycle(plist1, plist2);}else{//2)同环,两个入口点// 解决方案:一个入口点开始遍历一圈,看环上是否有另一个入口点// 若找到则返回plist1的入口点ListNode* cur = ent1->next;while (cur != ent1){if(cur == ent2){return ent1;}cur = cur->next;}return NULL;//不相交}}}
阅读全文
1 0
- C语言实现单链表面试题--进阶(带环问题)
- C语言实现单链表面试题(进阶篇)
- C语言实现单链表面试题--进阶
- C语言实现单链表面试题--进阶
- c语言实现单链表面试题——进阶
- c语言实现单链表面试题之进阶篇
- C语言实现单链表面试题---进阶
- C语言实现单链表面试题-------进阶篇
- 【C】单链表面试题(进阶)
- c语言实现单链表面试题
- C语言实现单链表面试题(基础篇)
- C语言实现单链表面试题(基础篇)
- c语言实现单链表面试题(基础篇)
- C语言的单链表面试题----进阶
- C语言—链表面试题之带环问题的总结
- C语言实现单链表面试题汇总
- C语言实现单链表面试题--基础篇
- C语言实现单链表面试题--基础篇
- Android7.0中文文档(API) --- RadioButton
- 雕虫小技也重要--数据处理中的电子表格技巧
- C++ Algorithm 不改变参数的函数详解
- 第一篇
- IntelliJ使用指南—— 导入Eclipse的Web项目
- C语言实现单链表面试题--进阶(带环问题)
- C#学习笔记(1)_用EditPlus编译运行C#程序
- GoogLeNet
- Tomcat在Myeclipse中出现的问题(一)
- eclipse在启动时报错的解决方案
- Activity引入Fragment 不显示
- SimpleAdapter
- 不相交集(DisjointSet)
- Excel单元格出现####错误怎么办?