【链表篇】链表面试题集
来源:互联网 发布:追回前男友的套路知乎 编辑:程序博客网 时间:2024/05/20 18:01
原文:http://blog.csdn.net/dengsi23/article/details/7984291
1. 给定单链表,检测是否有环。如果有环,则求出进入环的第一个节点。
判断单向链表是否有环,可以采用快指针与慢指针的方式来解决。即定义一个快指针fast和一个慢指针slow,使得fast每次跳跃两个节点,slow每次跳跃一个节点。如果链表没有环的话,则slow与fast永远不会相遇(这里链表至少有两个节点);如果有环,则fast与slow将会在环中相遇。判断出链表有环以后,则需要算出进入环的第一个节点。在fast与slow第一次相遇后,设置一个节点pNode从链表的头部开始遍历,每次只遍历一个节点。这样,当fast与slow再次相遇时,pNode所处的位置便是环的首部。以下该问题的实现源码(C语言描述):
- LNode* GetLoopNode(LNode* head)
- {
- //前置条件的判断
- if (!head)
- {
- return NULL;
- }
- //定义一个快指针和一个慢指针
- LNode* fast = head;
- LNode* slow = head;
- while (fast && (fast->next))
- {
- fast = fast->next->next;
- slow = slow->next;
- if (fast == slow)
- {
- //如果有环,则返回环的第一个节点
- slow = head;
- while (1)
- {
- fast = fast->next;
- slow = slow->next;
- if (fast == slow)
- {
- break;
- }
- }
- return slow;
- }
- }
- return NULL;
- }
注:原文并未解释在找到环后,为啥通过齐步走,能找到环的首部。个人觉得,此处可以这样简单理解,把链表表头代表的链缠绕到环上。
2. 给定两个单链表,检测两个链表是否有交点,如果有返回第一个交点。
检测两个单链表是否有交点是很容易的,因为如果两个链表有交点,那么这两个链表的最后一个节点必须相同,所以只需比较最后一个节点即可。但是这种方案是无法求出第一个交点的,所以需要另辟蹊径。另外,判断是否有交点可以转换成链表是否有环的问题。让一个链表的最后一个节点指向第二个链表的头结点,这样的话,如果相交,则新的链表是存在环的,并且交点便是环的入口点。
3. 只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。
由于没有给定链表的头结点,所以无法获取需要删除节点的前驱结点,这样就无法使用常规的方法去解决。在《编程之美》这本书里面给出一个非常精妙的解法,也就是采用了狸猫换太子的思想。以下是实现源码:
- void DeleteNode(LNode* pNode)
- {
- //如果pNode是最后一个节点,则该问题误解
- if (!pNode || !(pNode->next))
- {
- return;
- }
- //获取pNode的后驱节点
- LNode* qNode = pNode->next;
- //将qNode的值赋给pNode,并删除qNode
- pNode->data = qNode->data;
- pNode->next = qNode->next;
- free(qNode);
- }
4. 给定单链表头结点,删除链表中倒数第k个结点
这个问题的关键是需要获取倒数第k个节点。如何获取呢?这里,需要两个指针p和q,p指向头结点,q指向距离头结点为k的节点。这样p和q每次遍历一个节点,当q遍历到末尾的时候,p指向的节点即为倒数第k个节点。然后删除即可。以下是实现源码(这里获取的是倒数第k+1个节点,因为需要删除的是倒数第k个节点):
- void DelLastKNode(unsigned int k, LNode* head)
- {
- //前置条件判断
- if (!head || k <= 0)
- {
- return;
- }
- LNode* pNode = head;
- LNode* qNode = head;
- //将qNode遍历到正数第k + 1个节点
- unsigned int i;
- for (i = 0; i < k; i++)
- {
- qNode = qNode->next;
- }
- //获取倒数第k + 1个节点
- while (qNode->next)
- {
- pNode = pNode->next;
- qNode = qNode->next;
- }
- //删除倒数第k个节点
- LNode* temp = pNode->next;
- pNode->next = temp->next;
- free(temp);
- }
注: 个人觉得原文此处不严谨。
- unsigned int i;
- for (i = 0; i < k; i++)
- {
- qNode = qNode->next;
- }
- unsigned int i;
- for (i = 0; i < k; i++)
- {
- qNode = qNode->next;
- if (!qNode)
- return; // 不超过k+1个结点时,直接退出。
- }
另外,个人觉得此函数在处理刚好只有k个结点时,会需到问题。因为它需要获取的是倒数k+1个结点。
相比之下,另一种方法,获取倒数第k个结点,然后用狸猫换太子之法删掉则能处理掉此种情况。
- 【链表篇】链表面试题集
- 【链表篇】链表面试题集
- 常见链表面试题
- 链表面试题
- 常见链表面试题
- 链表面试题小结
- 链表面试题小结
- 链表面试题
- 链表面试题
- 链表面试题
- 常见链表面试题
- 链表面试题集锦
- 链表面试题整理
- 链表面试题
- 链表面试题小结
- 链表面试题小结
- 链表面试题小结
- 单链表面试题
- 90后大学生更应主动出击 切莫坐以待毙
- SQL 语句查看表结构
- 设计模式——代理模式(Proxy Pattern)
- 黑马程序员--利用JDBC访问数据库
- Servlet 工作原理解析
- 【链表篇】链表面试题集
- 2014-10月工作计划
- Js:Js对象——基本对象
- 黑马程序员-银行管理系统
- Java Notes
- 设计模式——工厂模式(Factory Method)
- linux下编译、连接及运行时环境变量设置(boost库为例)
- unity3d 根据指定的Assets下的文件夹路径 返回这个路径下的所有文件名
- RTSP协议详解