数据结构面试题及答案+字节跳动+滴滴+腾讯高频面试题之链表专题(一)
高频面试题之链表专题(一)
本节目标
-
1、合并两个有序单链表,要求合并后依旧有序。(2020年字节跳动一面原题)
-
2、查找单链表的倒数第K个节点。(2020年滴滴一面原题)
-
3、判断两个单链表是否相交?若相交,求出交点。(2020年腾讯一面原题)
-
4、判断单链表是否带环?若带环,求出环的长度?若带环求出环的入口点。(2020年腾讯一面原题)
1、合并两个有序单链表,要求合并后依旧有序。
高频考察的大厂云图:
解题思路:
先创建一个空链表头节点,然后依次从两个有序链表中选取最小的进行尾插操作进行合并。
代码实现:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1 == NULL)
return l2;
else if(l2 == NULL)
return l1;
ListNode* head = NULL, *tail = NULL;
//创建空链表的头,方便下面进行尾插
head = tail = new ListNode;
while(l1 && l2)
{
// 取小的进行尾插
if(l1->val < l2->val)
{
tail->next = l1;
tail = tail->next;
l1 = l1->next;
}
else
{
tail->next = l2;
tail = tail->next;
l2 = l2->next;
}
}
//其中一个链表剩余节点挂到后面
if(l1)
tail->next = l1;
else
tail->next = l2;
ListNode* list = head->next;
delete head;
return list;
}
};
2、查找单链表的倒数第K个节点。
高频考察的大厂云图:
解题思路:
快慢指针法 fast, slow, 首先让fast先走k步,然后fast,slow同时走,fast走到末尾时,slow走到倒数第k个节点。
代码实现:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
ListNode* slow = pListHead;
ListNode* fast = slow;
// 让fast指针先走K步,跟slow指针拉开K步的差距
while(k--)
{
// 这里需要注意链表可能没有K步长
if(fast)
fast = fast->next;
else
return NULL;
}
// fast到尾时,slow指向倒数第k个
while(fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
};
3、判断两个单链表是否相交?若相交,求出交点。
高频考察的大厂云图:
解题思路:
- 若两个链表的最后一个节点的指针相同,则相交。
- 计算出两个链表的长度,让指向长链表指针先走他们之间的长度差,然后长链表和短链表指针同时走,第一个节点指针相同的点就是交点。
代码实现:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int lenA = 0, lenB = 0;
ListNode* curA = headA, *curB = headB;
//先计算两个链表的长度
while(curA) {
++lenA;
curA = curA->next;
}
while(curB) {
++lenB;
curB = curB->next;
}
int gap = abs(lenA-lenB);
struct ListNode* longList = headA, *shortList = headB;
if(lenA < lenB) {
longList = headB;
shortList = headA;
}
//让长链表先走他们之间的长度差
while(gap--) {
longList = longList->next;
}
//两个链表同时走,直到遇到相同的节点
while(longList && shortList) {
if(longList == shortList) {
return longList;
}
else {
longList = longList->next;
shortList = shortList->next;
}
}
return NULL;
}
};
4、判断单链表是否带环?若带环,求出环的长度?若带环,求出环的入口点。
判断带环的OJ链接:https://leetcode-cn.com/problems/linked-list-cycle/
求环的入口点OJ链接:https://leetcode-cn.com/problems/linked-list-cycle-ii/
高频考察的大厂云图:
解题思路:
- 定义快慢指针fast,slow, fast指针一次走2步,slow指针一次走1步,如果链表确实有环,slow指针进入环以后,fast指针一定会在环内追上slow指针。
- 针对上一个问题,面试官通常会加餐:请证明slow指针一次走1步,fast指针一次走2步,为什么一定能追上而不会错过。那么slow走1步,fast走3步呢?那么slow走1步,fast走4步呢?
- 求环的长度很好求,从相遇点再走一圈就可以求出来了。
- 求环的入口点请看下面的证明。
公式推导如上图所示, 如果链表存在环,则fast和slow会在环内相遇,定义相遇点到入口点的距离为X,定义环的长度为C,链表头到入口点的距离为L,slow进入环之前,fast已经在环中跑了N圈了,fast在slow进入环之后一圈内追上slow,则会得知:
slow所走的步数为:L + X
fast所走的步数为:L + X + N * C
并且fast所走的步数为slow的两倍,故:
2*(L + X) = L + X + N * C
即: L = N * C - X
所以从相遇点开始slow继续走,让一个指针从头开始走,相遇点即为入口节点
代码实现:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
return true;
}
return false;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
//走到相遇点
if(slow == fast)
{
// start从链表的头开始走,meet从相遇点开始走,第一次碰到的点就是入口点,这是上面的公式证明出来的
ListNode* meet = slow;
ListNode* start = head;
while(meet != start)
{
meet = meet->next;
start = start->next;
}
return meet;
}
}
return NULL;
}
};
上述的内容,如果你没有明白的地方,这是我们录制的视频讲解,请参考
如果你对我写的内容感兴趣,并且对你有帮助,请你点个赞哦
你对哪些面试题感兴趣,你可以留言,我们会出视频,带你学习哦~
博主和团队推出一个免费的公众号栏目:IT笔试面试真题讲解,每天发布一个视频讲解IT公司笔试面试真题。
欢迎扫码关注哦