单链表面试题——进阶篇
来源:互联网 发布:beyond compare mac版 编辑:程序博客网 时间:2024/06/05 09:19
1.判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法的时间复杂度&空间复杂度。
判断是否带环:利用快慢指针,快指针每次走两步,慢指针每次走一步,如果快慢指针相遇,则该链表带环。
ListNode* IsHaveLoop(ListNode* plist){ if (plist == NULL) { return NULL; } ListNode* fast = plist; ListNode* slow = plist; while (fast->next&&fast) { fast = fast->next->next; slow = slow->next; if (fast == slow) { return slow; } } return NULL;}
求环的长度:相遇之后,每次追一步,再次相遇刚好追一圈——环的长度。
int SizeofLoop(ListNode* plist)//求环长{ ListNode* meet = IsHaveLoop(plist); if (meet) { int count = 1; ListNode* tmp = meet->next; while (tmp != meet) { tmp = tmp->next; count++; } return count; } return 0;}
求环入口点: T——尾长(非环长度),S——慢指针入环到被追上, C——快指针追慢指针多跑的圈。那么,慢指针走的路程为 T+S,快指针走的路程为 T+S+C,可得 2(T+S)=T+S+C,T=C-S,此时,一个指针从起点出发走T步,一个指针从快慢指针相遇点出发走 C-S 步,此时两指针刚好都在入口点。
ListNode* EnterNode(ListNode* plist) { ListNode* meet = IsHaveLoop(plist); if(meet) { while (meet != plist) { meet = meet->next; plist = plist->next; } return plist; } return NULL;}
2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
ListNode* Intersect(ListNode* pList1, ListNode* pList2){ int count1 = 0, count2 = 0; ListNode* p1 = pList1, *p2 = pList2; while (p1->next) { count1++; p1 = p1->next; } while (p2->next) { count2++; p2 = p2->next; } if (p1 != p2) return NULL; if (count1 >= count2) { count1 -= count2; while (count1--) pList1 = pList1->next; while (pList1 != pList2) { pList1 = pList1->next; pList2 = pList2->next; } return pList1; } else { count2 -= count1; while (count2--) pList2 = pList2->next; while (pList1 != pList2) { pList1 = pList1->next; pList2 = pList2->next; } return pList1; }}
3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
ListNode* Intersect(ListNode* plist1, ListNode* plist2)//判断链表是否相交升级版{ //先判断是否为空 if ((plist1 == NULL) || (plist2 == NULL)) { return NULL; } ListNode* enter1 = EnterNode(plist1); ListNode* enter2 = EnterNode(plist2); //1和2:若两个链表都无环,则直接用题目二的函数解决 if ((enter1 == NULL) && (enter2 == NULL)) { return IsListIntersect(plist1, plist2); } //4:若一个有环,一个无环,则不想交,返回NULL else if ((enter1 == NULL) && (enter2 != NULL) || (enter1 != NULL) && (enter2 == NULL)) { return NULL; } //3: 若入口点相同都在尾巴,去掉环,转化成无环相交问题 else if (enter1 == enter2) { enter1->next = NULL; enter2->next = NULL; return IsListIntersect(plist1, plist2); } //6 :同环,两个入口点 一个入口点开始遍历一圈,看环上是否有另一个入口点 // 找到则返回plist1的入口点 else { ListNode* tmp = enter1->next; while (tmp != enter1) { if (tmp == enter2) { return enter1; } tmp = tmp->next; } return NULL; }}
4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
ComplexNode* CopyList(ComplexNode* plist){ if (plist == NULL) { return NULL; } ComplexNode* newnode = NULL; ComplexNode* tmp = plist; //1.1 插入节点 while (tmp != NULL) { newnode = (ComplexNode*)malloc(sizeof(ComplexNode)); newnode->_data = tmp->_data; newnode->_next = tmp->_next; newnode->_random = NULL; tmp->_next = newnode; tmp = tmp->_next->_next; } //1.2开始连接random tmp = plist; newnode = plist->_next; while (tmp != NULL) { if (tmp->_random != NULL) { newnode->_random = tmp->_random->_next; } tmp = tmp->_next->_next; if (tmp) { newnode = tmp->_next; } } //2.分离两个链表 ComplexNode* res = plist->_next; tmp = plist; tmp->_next = tmp->_next->_next; tmp = tmp->_next; newnode = plist->_next; while ((tmp->_next != NULL)&&(tmp != NULL)) { newnode->_next = newnode->_next->_next; tmp->_next = tmp->_next->_next; tmp = tmp->_next; newnode = newnode->_next; } return res;}
阅读全文
1 0
- 常见的单链表面试题——进阶篇
- 单链表面试题——进阶篇
- 单链表面试题——进阶篇
- c语言实现单链表面试题——进阶
- C语言实现单链表面试题(进阶篇)
- c语言实现单链表面试题之进阶篇
- C语言实现单链表面试题-------进阶篇
- 【C】单链表面试题(进阶)
- 单链表面试题——基础篇
- 单链表面试题——基础篇
- 链表面试题 进阶
- C语言实现单链表面试题--进阶
- C语言的单链表面试题----进阶
- C语言实现单链表面试题--进阶
- C语言实现单链表面试题---进阶
- 单链表面试题
- 单链表面试题
- 单链表面试题
- Centos上下载软件包步骤
- centos上的软件管理
- yum下载与管理软件包
- 安装事件过滤器(installEventFilter) ,过滤子控件事件,截获控件按键、鼠标事件
- 简单安装epel的仓库方法
- 单链表面试题——进阶篇
- centos下文件操作实例
- Linux下文件操作
- 在磁盘上新建分区(包含swap分区)
- Makefile中通过sed命令生成文件系统的selinux的配置文件vendor_filesystem_config.txt
- vi基本操作(练习题案例)
- js的二级联动实现省份城市的选择
- C++类再写一遍学生查分系统
- 3d建模个人流程