内容会持续更新,有错误的地方欢迎指正,谢谢!
前言
单链表虽然简单,但是由于其涉及很多的指针操作,细微之处都特别考验程序员的能力,所以,是面试时被提及最频繁的数据结构,博主在此列出一些单链表常见的题型。
目录
现在看不懂目录里的解决方法的同志,请跳过,直接进入下方内容。
以下所言的中指针即当前指针。
1、逆序构造单链表
前中指针。定义一个前指针,再在循环里申请新结点(即当前结点)的空间并为之赋值并让其next指向前指针并更新前指针。
2、从尾到头打印链表
法一:中指针+利用栈的逆序特性
法二:中指针+利用递归(存到vector)的逆序特性
3、反转链表
法一:迭代(前中后三个指针)
法二:递归(前中指针,递归前半部分使当前结点走到最后一个结点、前结点走到倒数第二个结点,递归后半部分只需利用前指针进行反转)
4、找出单链表的中间结点
快慢指针(快指针一次两步,慢指针一次一步)
5、链表中环的入口结点
快慢指针求得环中一点,利用该点求得环中结点数,再用前后指针,邂逅点就是目标点。
6、两个链表的第一个公共结点
法一:尾结点和其中一个链表的头结点相连,就变成了上一个问题
法二:先通过两个指针求出两个链表的长度差,再用前后指针,邂逅点就是目标点。
7、链表升序排序
前后指针+快排思想
8、链表中倒数第k个结点
法一:前后指针,倒数第k个结点就是正着数第n-k+1个结点,前指针先走k-1步,再一起走。前指针到达最后一个结点时,后指针则到达了目标结点。
法二:也可以先求总的结点数n,再让头结点直接走n-k步,到达n-k+1处的结点即可。
9、删除指定结点
法一:前中后指针,时间复杂度O(n)
法二:中后指针,若要删除2,则把2和3的val交换,2的next指向3的next,即4,再delete3。
10、合并两个升序的链表
法一:递归,两个链表的头指针+目标链表的头指针
法二:迭代,两个链表的头指针+目标链表的头指针
本文默认已定义了以下结点结构:
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) { }
//尽量使用初始化列表,因为它调用的是赋值构造函数,可少调用一次默认构造函数,快一些。
};
1、逆序构造单链表
前中指针。逆序构造单链表就是先让最后一个结点指向nullptr,再让倒数第二个结点指向最后一个结点。。。思路:先申请新结点的空间,再为之赋值。
ListNode* DescConstruct(ListNode* pHead)
{
ListNode* preNode=nullptr;//由于是逆序,所以需定义一个前结点
int val;
while(cin>>val&&val!=-1)//-1表示结束输入
{
ListNode* curNode=new ListNode;//为新结点开辟空间
curNode->val=val;
curNode->next=preNode;
preNode=curNode;
}
pHead->next=preNode;//让头结点指向“第一个结点”,因为你把身体搭建好了,要有个脑壳嘛
return pHead;
}
2、从尾到头打印链表
就是倒序打印单链表,输入1->2->3->4,输出4->3->2->1,注意链表为空的情况,可以使用栈或递归,时间复杂度为O(n)
//使用栈,先依次入栈,再依次出栈即可,具体实现略
//使用递归
vector<int> res;
vector<int> printListFromTailToHead(ListNode* head)
{
ListNode* pNode=head;
if(pNode!=nullptr)
{
printListFromTailToHead(pNode->next);
res.push_back(pNode->val);
}
return res;
}
3、反转链表
例如:假设现有链表:4->3->2->1,进行反转操作后,链表变成:1->2->3->4。从头到尾遍历原链表,将每个结点摘下放在新链表的最前端。需要前中后三个指针,一个指向前一个结点,一个指向当前结点,一个指向下一个结点,再进行反转。注意链表为空和只有一个结点的情况。时间复杂度为O(n)
//迭代实现
ListNode* ReverseList(ListNode* pHead)
{
if(pHead==nullptr||pHead->next==nullptr)
return pHead;
ListNode* preNode=nullptr;
ListNode* curNode=pHead;
ListNode* nextNode=curNode->next;//只用于记录下一个结点的位置
while(curNode!=nullptr)
{
curNode