链表相关的热点面试题(一)
2017-05-15 13:28
274 查看
先把相关的题目给出来
1. 从尾到头打印单链表
2. 删除一个无头单链表的非尾节点
3. 在无头单链表的一个非头节点前插入一个节点
4. 逆置/反转单链表
5. 单链表排序
6. 合并两个有序链表,合并后依然有序
7. 查找单链表的中间节点, 要求只能遍历一次链表
先把单链表结构给出来
从尾到头打印单链表
这就是最简袋的递归思想。
删除一个无头单链表的非尾节点(链表的O(1)删除)
乍一看是不是有点没头绪,甚至都不知道题目是什么意思。
一般的我们要删除一个单链表节点pos,都是找到它的前一个节点prev,然后让prev->next指向pos->next,但是这里说要删除一个无头节点,也就是我们没办法通过遍历找到pos的前一个节点,那怎么办呢?
其实思路也是很简单的,我们可以通过赋值的方式,只对节点数据就行改变,可以把要删除节点pos->next的数据,也就是del->value赋值给pos,然后再删除del这个节点就好了。
这道题也叫做 链表的O(1)删除。
在无头单链表的一个非头节点前插入一个节点
刚做完上面那道删除,这又来插入是不是感觉很简单。
思路是一样的:
我们先申请一个节点newnode,然后将newnode插入到pos后面,然后交换newnode和pos的数据。
逆置/反转单链表
单链表排序( 冒泡排序)
其实就和普通的冒泡排序一样
合并两个有序链表,合并后依然有序
这里是用递归的思想,每次进来都找数据小的那个节点,让小的节点最为新的头节点,知道有一个链表走到NULL位置。
查找单链表的中间节点, 要求只能遍历一次链表
这个就是快慢指针,快指针一次走两步,慢指针一次走一步。
最后快指针fast走到尾节点的时候,慢指针刚好到中间节点。
1. 从尾到头打印单链表
2. 删除一个无头单链表的非尾节点
3. 在无头单链表的一个非头节点前插入一个节点
4. 逆置/反转单链表
5. 单链表排序
6. 合并两个有序链表,合并后依然有序
7. 查找单链表的中间节点, 要求只能遍历一次链表
先把单链表结构给出来
template<typename T> struct Node { Node<T>* _next; T _value; Node(const T& value = T()) :_value(value) , _next(NULL) {} };
从尾到头打印单链表
这就是最简袋的递归思想。
void ReversePrint(const Node<int>* node) { if (node == NULL) return; ReversePrint(node->_next); cout << node->_value << " "; }
删除一个无头单链表的非尾节点(链表的O(1)删除)
乍一看是不是有点没头绪,甚至都不知道题目是什么意思。
一般的我们要删除一个单链表节点pos,都是找到它的前一个节点prev,然后让prev->next指向pos->next,但是这里说要删除一个无头节点,也就是我们没办法通过遍历找到pos的前一个节点,那怎么办呢?
其实思路也是很简单的,我们可以通过赋值的方式,只对节点数据就行改变,可以把要删除节点pos->next的数据,也就是del->value赋值给pos,然后再删除del这个节点就好了。
void EraseNotTail(Node<int>* node) { assert(node&&node->_next);//去除空节点和尾节点的情况 Node<int>* del = node->_next; node->_value = del->_value; node->_next = del->_next; delete del; }
这道题也叫做 链表的O(1)删除。
在无头单链表的一个非头节点前插入一个节点
刚做完上面那道删除,这又来插入是不是感觉很简单。
思路是一样的:
我们先申请一个节点newnode,然后将newnode插入到pos后面,然后交换newnode和pos的数据。
void InsertFrontNode(Node<int>* node) { assert(node);//去除节点为空情况 Node<int>* newnode = new Node<int>(5); newnode->_next = node->_next; node->_next = newnode; swap(node->_value, newnode->_value); }
逆置/反转单链表
void Reverse(Node<int>*& head) { assert(head!=NULL); Node<int>* newhead = head; Node<int>* cur = head->_next; head->_next = NULL; while (cur) { Node<int>* tmp = cur->_next; cur->_next = newhead; newhead = cur; cur = tmp; } }
单链表排序( 冒泡排序)
其实就和普通的冒泡排序一样
void BubbleSort(Node<int>* head) { assert(head); if (head->_next== NULL) return; Node<int>* cur = head; Node<int>* tail = NULL; while (cur != tail) //当尾指针不等于头指针时进行冒泡 { while (cur->_next != tail) //控制cur指针最后到的位置是倒数第二个节点 { if (cur->_value > cur->_next->_value) { swap(cur->_value, cur->_next->_value); } cur = cur->_next; } tail = cur; cur = head; } }
合并两个有序链表,合并后依然有序
这里是用递归的思想,每次进来都找数据小的那个节点,让小的节点最为新的头节点,知道有一个链表走到NULL位置。
Node<int>* MergeTwoList(Node<int>*& head1, Node<int>*& head2) { if (head1 == NULL) return head2; if (head2 == NULL) return head1; Node<int>* newhead = head1->_value < head2->_value ? head1 : head2; if (newhead == head1) newhead->_next = MergeTwoList(head1->_next, head2); if (newhead == head2) newhead->_next = MergeTwoList(head1, head2->_next); return newhead; }
查找单链表的中间节点, 要求只能遍历一次链表
这个就是快慢指针,快指针一次走两步,慢指针一次走一步。
最后快指针fast走到尾节点的时候,慢指针刚好到中间节点。
Node<int>* FindMidNode( Node<int>* head) { assert(head); Node<int>* slow= head; Node<int>* fast = head; while (fast != NULL) { if(fast->next==NULL) break; fast=fast->_next->_next; slow = slow->_next; } return slow; }
相关文章推荐
- 链表相关的热点面试题(二)
- 【C语言】单链表的相关热点面试题(包括:从尾到头打印,逆置,冒泡,寻找中间节点,倒数k节点)
- 【C语言】单链表的相关热点面试题(包括:从尾到头打印,逆置,冒泡,寻找中间节点,倒数k节点)
- 顺序表和链表的相关热点面试题
- 链表相关面试题
- 链表相关面试题
- 面试题解(1):单向链表相关
- 【数据结构】链表的原理及与其相关的常见面试题总结
- C语言实现无头单链表及链表相关面试题(重点!)
- 单链表的相关面试题
- 判断链表环相关的面试题
- 【每日面试题】链表相关问题2
- 单链表的实现和相关面试题及其详解(C语言)
- 【链表复习】链表相关面试题
- 链表相关面试题
- 面试题5: 链表的相关操作
- 链表相关面试题(基础篇)
- 链表相关笔试面试题
- 链表相关面试题总结大全
- 【数据结构】链表的原理及与其相关的常见面试题总结