您的位置:首页 > 职场人生

链表常见面试题一:基本问题

2016-04-11 20:04 716 查看
本文列举出了7个链表常见的面试题,其他面试题请阅读下一篇博客

面试题1:删除非尾节点
删除非尾节点,只告诉一个当前节点的位置,将该位置的节点删除。
解题思路:
删除该位置的节点,由于我们不知道它的前一个节点的位置,不能直接将它的前一个节点与它的后一个节点连接起来。
因此,我们需要用另一种方法:
将该节点的后一个节点的元素赋值给该节点,然后删除该节点的后一个节点。
650) this.width=650;" title="图片2.png" alt="wKioL1agYeKyRY9hAABX5i61Bpo619.png" src="http://s4.51cto.com/wyfs02/M01/79/FE/wKioL1agYeKyRY9hAABX5i61Bpo619.png" />

void ReverseList(pList* pHead)
{
assert(pHead);
pLinkNode cur = *pHead;
pLinkNode prev = NULL;
pLinkNode NewHead = NULL;
while (cur)
{
prev = cur;
cur = cur->next;
prev->next = NewHead;
NewHead = prev;

}
*pHead = NewHead;
}
面试:3:排序单链表
解题思路:
排序链表可以用冒泡排序的思想,从前往后遍历链表,要是前一个元素比后一个元素大,那么就交换两个元素,遍历一次的结果 是将链表中最大的元素放在最后。
面试题4:在当前节点前插入一个数据x
解题思路:
基本思想是将x插入到当前节点之后,然后交换两个节点的元素。
650) this.width=650]
[code]void InsertFrontNode(pLinkNode pos, DataType x)
{
assert(pos);
pLinkNode NewNode = BuyNode(x);
DataType tmp = 0;
NewNode->next = pos->next;
pos->next = NewNode; //将要插入的元素插入到当前节点的后面
tmp = NewNode->data;//交换两元素
NewNode->data = pos->data;
pos->data = tmp;
}
面试题5:合并两个有序列表
解题思路:
基本思想是首先确定一个合并以后的头结点,比较两个链表的第一个元素,较小的元素所在的节点为头结点。然后比较两个链表剩余节点的第一个节点,将较小的一个连在头结点的后面,再次比较剩余的节点,然后依次将较小的节点连在新链表的后面,直到有一个链表为空。将另一个链表的剩余节点全都连在新链表上。
有两种方法可以实现:
一、非递归的方法:
pLinkNode Merge(pList l1, pList l2)
{
pList NewHead = NULL;
pLinkNode cur = NULL;
//若有一个链表为空,返回不是空链表的那个链表,若都为空,返回任意一个
if (l1 == NULL || l2 == NULL)
{
if (l1)
return l1;
else
return l2;
}

if (l1->data < l2->data) //若l1的第一个元素比l2的第一个元素小,那么l1的第一个节点为头节点
{
NewHead = l1;
l1 = l1->next;
}
else //若l2的第一个元素比l1的第一个元素小,那么l2的第一个节点为头节点
{ //若两个元素相等则任意一个做头节点都可以,这里让l2的元素做头节点
NewHead = l2;
l2 = l2->next;
}
cur = NewHead;
while (l1 && l2)
{
if (l1->data < l2->data) {
cur->next = l1;
l1 = l1->next;
}
else
{
cur->next = l2;
l2 = l2->next;
} //将较小的元素连在新链表的后面
cur = cur->next;
}
if (l1)
{
cur->next = l1; // 若l1不为空,将l1剩余的元素连接在新链表的后面
}
else
{
cur->next = l2;
} //若l2不为空,将l2剩余的元素连接在新链表的后面
return NewHead;
}
二、递归的方法:
因为每次都是将两个链表上的较小的节点连在新链表的后面,因此可以用递归方法实现
pLinkNode _Merge(pList l1, pList l2)
{
pList NewHead = NULL;
pLinkNode cur = NULL;
if (l1 == NULL || l2 == NULL)
{
if (l1)
return l1;
else
return l2;
}
if (l1->data < l2->data)
{
NewHead = l1;
NewHead->next = _Merge(l1->next, l2);
}
else
{
NewHead = l2;
NewHead->next = _Merge(l1, l2->next);
}
return NewHead;
}
面试题6:查找中间节点
解题思路:
用两个指针同时从头节点开始向后遍历,一个快指针一次走两步,另一个慢指针一次走一步,直快指针走到结尾,则指针所在的位置就是中间节点。
pLinkNode FindMidNode(pList head)
{
pLinkNode fast = head;
pLinkNode slow = head;
while (fast && fast->next)
{
fast = fast->next->next; //快指针一次走两步
slow = slow->next;       //慢指针一次走一步
}
return slow;              //返回中间节点
}
面试题7: 删除单链表的倒数第k个节点(k > 1 && k < 链表的总长度) 时间复杂度O(N)
解题思路:
要求遍历一遍删除链表中倒数第k各节点,可以用两个指针,第一个指针先走k-1步,然后第一个指针和第二个指针一起走,当第二个指针到达链表末尾时,第一个指针所在的位置就是倒数第k各节点。
然后根据删除非尾节点的方法将它删除(删除非尾节点的方法可参考面试题1)。
void DelKNode(pList *pHead, int k)
{
assert(k > 1);
pLinkNode l1 = *pHead;
pLinkNode l2 = *pHead;
pLinkNode del = NULL;
while (--k && l2->next) //第二个指针先走k-1步
{
l2 = l2->next;
}
if (l2->next == NULL)      //k>=链表总长度
{
return;
}
while (l2->next)       //两个指针一起走
{
l2 = l2->next;
l1 = l1->next;
}
del = l1->next;
l1->data = l1->next->data;
l1->next = l1->next->next;
free(del);                 //删除倒数第k各节点
del = NULL;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: