先前已经写过一些单链表的基本操作:单链表的基本操作(若有兴趣可先看看链表的基本操作)
这次链表相关的面试题是建立在这个之上写的,测试的时候会调用的其中的一些函数。
今天主要说以下几个常见的链表面试题
1.查询链表中间结点
2.只给出一个位置,删除非尾结点
3.逆序链表
查询链表的中间结点,我们知道,单链表只能顺序访问,那么怎么查找中间结点呢?你可能会想到,先遍历一遍求出链表长度,然后再遍历一遍找出中间结点就可以了啊。没错,这样做能产生结果,但是相对的时间复杂度就高了,因为你把链表遍历了两遍!如果面试官要求时间复杂度为O(n),那这样做是万万不能的。
因此,一般这种题我们优先考虑时间复杂度最低的算法。具体做法:
设置快慢指针,这种思想在很多链表的面试题里都会用到,我们应该有这种意识。设置一个快指针,一个慢指针,快指针一次走两步,慢指针一次走一步。那么当快指针指向链表尾部的时候,慢指针刚好在链表的中间位置!至于偶数的情况下,你可以根据要求或者自己喜好选择哪一个做中间结点。思路很简单,来看看代码。
pLinkNode FindMidNode(pLinkList pList)
{
assert(pList);
pLinkNode fast = pList->pHead;
pLinkNode slow = pList->pHead;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
这里再次把构建链表的结构体放出来,以防有人看不懂~
typedef int DataType;
typedef struct LinkNode
{
DataType data;
struct LinkNode *next;
}LinkNode,*pLinkNode;
typedef struct LinkList
{
LinkNode *pHead;
}LinkList,*pLinkList;
那么测试一下吧
test7()
{
LinkList list;
pLinkNode ret = NULL;
InitLinkList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
PushBack(&list, 6); //构建了一个链表,中间结点为4
PrintList(&list);
ret = FindMidNode(&list);
printf("%d", ret->data);
}
接下来看第二个,删除非尾结点,题目说了,只给位置,那要咋删呢?不给头结点的话没办法遍历啊!遍历不了就找不到要删除结点的前一个结点,以前用的删除的方法这里是不能用了。具体做法: 删除结点即删除结点对应的数据域,那么把要删除结点的后面一个结点的数据域保存到要删除的结点里面,然后删除它后面的结点即可。
代码如下:
void EraseNotTail(pLinkNode pos)
{
pLinkNode del = NULL;
if (pos->next == NULL)
{
return;
}
del = pos->next;
pos->data = del->data;
pos->next = del->next;
free(del);
}
测试:
test8()
{
LinkList list;
pLinkNode ret = NULL;
InitLinkList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
PushBack(&list, 6);
PrintList(&list);
ret = Find(&list, 3); //找到3的位置
EraseNotTail(ret); //删除3
PrintList(&list);
}
第三个问题,逆序链表。具体做法:设置三个指针,cur用来遍历链表,tmp,newhead每次更新结点的指针域。算法可能比较难理解,但是效率高。
函数实现:
void ReverseList(pLinkList pList)
{
assert(pList);
pLinkNode cur = pList->pHead;
pLinkNode NewHead = NULL;
while (cur)
{
pLinkNode tmp = cur;
cur = cur->next;
tmp->next = NewHead;
NewHead = tmp;
}
pList->pHead = NewHead;
}