【刷题篇】链表(上)

这篇具有很好参考价值的文章主要介绍了【刷题篇】链表(上)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档
  1. 前言🌈

前段时间我们学习了单向链表和双向链表,本期将带来3道与链表相关的OJ题来巩固对链表的理解。话不多说,让我们进入今天的题目吧!

🚀本期的题目有: 反转单链表链表的中间结点合并两个有序链表
  1. 反转单链表✨

a.题目

链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

b.题解分析(迭代)

🍡三指针法:我们可以直接在原链表的基础上修改指针的指向,定义三个指针对链表每个结点的指针进行反转,循环直到链表结束。具体过程动图如下:

链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

🔝头插法:在我们对链表进行进行头插时,假设依次插入1,2,3三个结点,最后结点的就是3,2,1,刚好相反。我们可以利用这个特性对链表进行反转,创建一个头指针指向一个空链表,然后遍历原链表的结点,将结点以头插的形式头插到新的链表中,最终新链表即为我们所需的反转链表(由于在头插过程中会改变结点的指向,所以我们也需要保存原链表的下一结点)。具体过程动图如下:

链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

c.AC代码(迭代)

struct ListNode 
{
    int val;
    struct ListNode *next;
};

//三指针法
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* n1 = NULL;
    struct ListNode* n2 = head;

    while (n2)
    {
        struct ListNode* n3 = n2->next; //保存下一结点位置
        n2->next = n1;
        n1 = n2;
        n2 = n3;
    }
    //n2为空时,n1即为反转后表头
    return n1;
}

//头插法
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* newhead = NULL; //新链表
    struct ListNode* first = head;
    while (first)
    {
        struct ListNode* next = first->next; //保存下一结点
        //进行头插
        first->next = newhead;
        newhead = first;
        first = next;
    }
    //全部结点头插完毕
    return newhead;

}

d.题解分析(递归)

除了用上面迭代的方式,我们还可以用递归的方式来实现反转链表,这会让代码更加简洁。我们可以先使用递归函数找到链表尾记为ret,ret即为反转后链表的头结点。当找到头结点后,递归函数开始返回,每次将当前结点的下一结点的next指针指向当前结点。由于递归返回是逆向的,因此当递归函数全部出栈后,链表的反转也就完成了。具体过程动图如下:

链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

e.AC代码(递归)

struct ListNode 
{
    int val;
    struct ListNode *next;
};
//递归法
struct ListNode* reverseList(struct ListNode* head) 
{
    if (head == NULL || head->next == NULL) //当只有一个结点、没有结点、递归到最后一个结点时返回
        return head;
    struct ListNode* cur = reverseList(head->next); //找到链表尾结点
    head->next->next = head; //让下一结点指向当前结点
    head->next = NULL; //当前结点指向空
    return cur; //返回反转后头结点
}
  1. 链表的中间结点📏

a.题目

链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

b.题解分析

本题我们可以使用快慢指针的方法来解答。

快慢指针 :含 快指针 慢指针 两个指针。快慢指针中的快慢指的是 移动的步长 ,即每次向前移动速度的 快慢 。例如可以让快指针每次沿链表向前移动2次,慢指针每次向前移动1次。

由于我们要求找到链表的中间结点,所以我们先定义一个快指针fast和一个慢指针slow指向第一个结点,然后让指针开始移动。规定快指针每次移动两步,慢指针每次移动一步,当快指针走到“链表尾”后,由于慢指针移动的步长为快指针一半,最后慢指针指向的即为链表的中间结点。

🔞本题有个需要注意的地方是:当链表的结点数为奇数时,链表只有一个中间结点,当快指针走到尾结点时慢指针即指向中间结点;但当链表的结点数为偶数时,快指针不可能走到尾结点,并且链表有两个中间结点,由于题目要求我们返回第二个结点,对应快指针指向空。综上,快指针fast移动停止的条件是fast == NULL || fast -> next == NULL。具体动图过程如下:

链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档
链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

c.AC代码

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while (fast != NULL && fast->next != NULL) //循环继续条件,对应于上述结束条件
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}
  1. 合并两个有序链表🍀

a.题目

链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

b.题解分析

这道题和合并两个有序数组有异曲同工之妙,只不过我们要合并的是链表,而不是数组。我们可以从左到右遍历两个链表比较结点的大小,将小的结点尾插到新链表。注意不是创建一个新结点然后尾插,题目要求新链表是通过已有结点拼接而成的。当一个链表遍历完毕后将另外一个链表的剩余结点尾插到新链表后即可完成合并。

我们在前面学习链表尾插时,不难发现,如果链表没有带哨兵位的头结点,尾插时需要额外考虑链表为空的情况,而我们正是需要从空链表开始尾插,所以为了代码简洁,我们可以创建带哨兵位的头结点来指向链表的有效部分,这样可以不需要进行分类讨论。具体过程动图如下:

链表 ret,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

c.AC代码

struct ListNode 
{
     int val;
     struct ListNode *next;
 };
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    struct ListNode* head = malloc(sizeof(struct ListNode)); //创建头结点
    head->next = NULL;
    struct ListNode* tail = head; //tail代表尾结点
    struct ListNode* p1 = list1;
    struct ListNode* p2 = list2;
    //遍历比较,尾插
    while (p1 != NULL && p2 != NULL)
    {
        if (p1->val > p2->val)
        {
            //把list2尾插到tail结点后
            tail->next = p2;
            tail = tail->next;
            p2 = p2->next;
        }
        else
        {
            //把list1尾插到tail结点后
            tail->next = p1;
            tail = tail->next;
            p1 = p1->next;
        }

    }
    //有一个链表遍历完毕
    if (p1)
    {
        //将p1及以后结点尾插
        tail->next = p1;
    }
    else if (p2)
    {
        //将p2及以后结点尾插
        tail->next = p2;
    }
    struct ListNode* cur = head->next; //头结点指向的部分即为我们所需的结果
    free(head); //释放创建的头结点
    return cur;
}

以上,就是本期的全部内容啦🌸

制作不易,能否点个赞再走呢🙏文章来源地址https://www.toymoban.com/news/detail-787145.html

到了这里,关于【刷题篇】链表(上)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构刷题训练——链表篇(一)

    目录 前言 题目一:链表的中间节点 思路 分析 题解  题目二:链表中倒数第k个结点 思路 分析  题解 题目三:合并两个有序链表 思路 分析 题解  方法二 题解  题目四:链表的回文结构 思路 分析 题解 总结         今天我将开启一个新的专栏,数据结构与算法刷题训练营

    2024年02月14日
    浏览(33)
  • 趣说数据结构(练习2) —— 顺序表/链表力扣刷题(中等难度)

    力扣原题:https://leetcode.cn/problems/reverse-linked-list-ii/ 题目描述 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left = right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。 示例 1 输入:head = [1,2,3,4,5], left = 2, right = 4 输出:[1,4,3,2,5] 示例 2 输入:h

    2024年02月01日
    浏览(55)
  • 【刷题篇】链表(上)

    前段时间我们学习了单向链表和双向链表,本期将带来3道与链表相关的OJ题来巩固对链表的理解。话不多说,让我们进入今天的题目吧! 🚀本期的题目有: 反转单链表 、 链表的中间结点 、 合并两个有序链表 a.题目 b.题解分析(迭代) 🍡 三指针法: 我们可以直接在原链表的

    2024年02月02日
    浏览(55)
  • 【刷题篇】链表(下)

    各位读者们好,本期我们来填填之前留下的坑,继续来讲解几道和链表相关的OJ题。但和上期单向链表不一样的是,我们今天的题目主要是于环形链表有关,下面让我们一起看看吧。 💻本期的题目有: 环形链表 、 环形链表II 、 求环形链表环长 a.题目 b.题解分析 第一种方法

    2024年01月25日
    浏览(43)
  • C语言数据结构--链表

    顺序表的问题及思考 问题: 1. 中间/头部的插入删除,时间复杂度为O(N) 2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。 3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到 200,我们再继续插入了5个数据,后面没有

    2024年02月05日
    浏览(44)
  • C语言数据结构——链表

    目录 前言 一、什么是链表 1.1链表的结构和概念 1.2 链表的分类 二、无头单向非循环链表 2.1 创建结构体 2.2 动态申请一个节点 2.3 单链表打印 2.4 单链表尾插/尾删 2.4.1 单链表尾插  2.4.2 单链表尾删 2.5 单链表头插/头删 2.5.1 头插 2.5.2 头删 2.6 单链表查找 2.7 单链表中间插入/中

    2024年02月16日
    浏览(55)
  • 数据结构:链表(Python语言实现)

    链表分为单链表、双链表、循环单链表和循环双链表。 本文以单链表为例,用python创建一个单链表数据结构,同时定义链表节点的增加、删除、查询和打印操作。 创建一个名为Node的节点类,节点类里面包含2个属性和1个方法。 分别为data数据域属性和next指针域属性。 has_va

    2024年02月16日
    浏览(53)
  • 双向链表(数据结构)(C语言)

    目录 概念 带头双向循环链表的实现 前情提示 双向链表的结构体定义 双向链表的初始化 关于无头单向非循环链表无需初始化函数,顺序表、带头双向循环链表需要的思考 双向链表在pos位置之前插入x 双向链表的打印 双链表删除pos位置的结点 双向链表的尾插 关于单链表的尾

    2024年02月04日
    浏览(62)
  • 数据结构链表(C语言实现)

            机遇对于有准备的头脑有特别的亲和力。本章将讲写到链表其中主要将写到单链表和带头双向循环链表的如何实现。    话不多说安全带系好,发车啦 (建议电脑观看) 。 附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗

    2024年02月10日
    浏览(39)
  • C语言实现链表--数据结构

    魔王的介绍:😶‍🌫️一名双非本科大一小白。 魔王的目标:🤯努力赶上周围卷王的脚步。 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥 ❤️‍🔥大魔王与你分享:很喜欢宫崎骏说的一句话:“不要轻易去依赖一个人,它会成为你的习惯当分别来临,你失去的不是某个人而是你精

    2024年02月02日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包