本文首发于我的公众号码农之屋(id: Spider1818),专注于干货分享,包含但不限于Java编程、网络技术、Linux内核及实操、容器技术等。欢迎大家关注,二维码文末可以扫。
导读:链表问题在面试过程中是非常重要也是非常基础的一环,主要就是考查面试者的编程功底,接下来将对常见的面试题进行归纳总结。
1、在O(1)时间删除链表节点
题目描述:给定链表的头指针和一个节点指针,在O(1)时间删除该节点。
分析:本题与《编程之美》上的「从无头单链表中删除节点」类似。主要思想都是「狸猫换太子」,即用下一个节点数据覆盖要删除的节点,然后删除下一个节点(如果节点是尾节点时,该方法就行不通了)。
代码如下:
void deleteRandomNode(Node *cur)
{
assert(cur != NULL);
assert(cur->next != NULL);
Node* pNext = cur->next;
cur->data = pNext->data;
cur->next = pNext->next;
delete pNext;
}
2. 单链表的转置
题目描述:输入一个单向链表,输出逆序反转后的链表。
分析:链表的转置是一个很常见、很基础的数据结构题了,非递归的算法很简单,用三个临时指针pre、head、next 在链表上循环一遍即可。
代码如下:
Node* reverseByLoop(Node *head)
{
if(head == NULL || head->next == NULL)
return head;
Node *pre = NULL;
Node *next = NULL;
while(head != NULL)
{
next = head->next;
head->next = pre;
pre = head;
head = next;
}
return pre;
}
3. 求链表倒数第k个节点
题目描述:输入一个单向链表,输出该链表中倒数第k个节点,链表的倒数第0个节点为链表的尾指针。
分析:设置两个指针p1、p2,首先p1和p2都指向head,然后p2向前走k步,这样p1和p2之间就间隔k个节点,最后p1和p2同时向前移动,直至p2走到链表末尾。
代码如下:
Node* theKthNode(Node *head,int k)
{
if(k < 0) returnNULL;
Node *slow,*fast;
slow = fast = head;
int i = k;
for(;i>0 && fast!=NULL;i--)
{
fast = fast->next;
}
if(i > 0) returnNULL;
while(fast != NULL)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
4. 求链表的中间节点
题目描述:求链表的中间节点,如果链表的长度为偶数,返回中间两个节点的任意一个,若为奇数,则返回中间节点。
分析:此题的解决思路和第3题「求链表的倒数第k个节点」很相似。可以先求链表的长度,然后计算出中间节点所在链表顺序的位置。但是如果要求只能扫描一遍链表,如何解决呢?最高效的解法和第3题一样,通过两个指针来完成。用两个指针从链表头节点开始,一个指针每次向后移动两步,一个每次移动一步,直到快指针移到到尾节点,那么慢指针即是所求。
代码如下:
Node* theMiddleNode(Node *head)
{
if(head == NULL)
returnNULL;
Node *slow,*fast;
slow = fast = head;
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
5. 判断单链表是否存在环
题目描述:输入一个单向链表,判断链表是否有环。
分析:通过两个指针,分别从链表的头节点出发,一个每次向后移动一步,另一个移动两步,两个指针移动速度不一样,如果存在环,那么两个指针一定会在环里相遇。
代码如下:
bool hasCircle(Node *head,Node *&circleNode)
{
Node *slow,*fast;
slow = fast = head;
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
circleNode = fast;
return true;
}
}
return false;
}
我的公众号「码农之屋」(id: Spider1818) ,分享的内容包括但不限于 Linux、网络、云计算虚拟化、容器Docker、OpenStack、Kubernetes、SDN、OVS、DPDK、Go、Python、C/C++编程技术等内容,欢迎大家关注。