单链表题目汇总

本文汇总了单链表常见的算法题,包括逆序构造、尾到头打印、反转、找中间结点、判断环、找公共结点、升序排序、找倒数k个结点、删除指定结点以及合并两个升序链表。采用快慢指针、迭代与递归等多种方法进行解析,适合面试复习和提升链表操作技能。
摘要由CSDN通过智能技术生成

内容会持续更新,有错误的地方欢迎指正,谢谢!

前言

单链表虽然简单,但是由于其涉及很多的指针操作,细微之处都特别考验程序员的能力,所以,是面试时被提及最频繁的数据结构,博主在此列出一些单链表常见的题型。

目录

现在看不懂目录里的解决方法的同志,请跳过,直接进入下方内容。

以下所言的中指针即当前指针。

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值