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

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

目录

前言

1.题目一:链表分割

1.1 思路

1.2 分析

 1.3 题解

2. 题目二:相交链表

2.1 思路

2.2 分析

2.3 题解

3. 题目三:环形链表

3.1 思路

3.2 分析

3.3 题解

总结


前言

        本期继续分享链表相关的OJ题目,在这个专栏博客中,我们将提供丰富的题目资源和解题思路,帮助读者逐步提高解题能力。同时,我们也将分享一些刷题技巧和经验,帮助读者更加高效地进行刷题训练。通过持之以恒的努力和不断的实践,相信读者可以在数据结构领域取得长足的进步。


1.题目一:链表分割

题目描述:数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

 题目链接:

链表分割https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId=8&&tqId=11004&rp=2&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

1.1 思路

        这道题目没有示例,这也是这道题的难点之一,我们只根据题意自己寻找示例,进行分析。题目的意思是说,给一个链表,给一个x值,把小于x的插入到x前边,大于x的插入到x的后边,且不可以打乱原链表中的次序(链表中的数据大小为乱序)。理解了题意,大家可以先自己思考一下解题思路。

        对于这道题的要求我们可以这样做:遍历原链表,将大于等于x的尾插到一个新链表,小于x的尾插到一个新链表,最后将两个链表合并。

1.2 分析

        这道题思路虽然非常简单,但是在实际编写代码时会有很多的坑。例如要考虑链表为NULL的情况,如果原链表中的所有值都大于x或小于x那就会造成两个链表中,其中一个链表为NULL。

 假设原链表为:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

 x值为3,那我们就可以把原链表分割成以下两个链表:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

         这道题目有两种方法,一种是使用带头节点的链表,一种是使用不带头节点的链表。对于链表掌握不熟悉的,本人推荐使用带头节点的链表,当然带头节点的链表对于这道题也可以简化代码。如果没有带头节点,那我们在初始化后尾插时就需要进行特殊处理。相对比较麻烦,所有我们这里推荐使用带头链表。

        如果带头结点两链表就是这样的:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

 将两个链表合并时也不需要特殊处理可以直接连接,如下图:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

 不用担心头节点怎么办,两个头节点最后会被销毁,销毁之后就是我们所需要的链表了。

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

         就算是第一个链表为空,也可以搞定:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

         连接的时候也不需要特殊处理,最后销毁两个头节点即可。

 1.3 题解

根据分析的思路,我们对代码进行编写:

ListNode* partition(ListNode* pHead, int x) {
        struct ListNode* head1,*head2,*tail1,*tail2;
        head1=tail1=(struct ListNode*)malloc(sizeof(struct ListNode));//创建两个头节点
        head2=tail2=(struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode* cur=pHead;    
        while(cur)                    //遍历原链表
        {
            if(cur->val < x)          //小于x就尾插到链表1
            {
                tail1->next=cur;
                tail1=tail1->next;
            }
            else                      //大于等于x就尾插到链表2
            {
                tail2->next=cur;
                tail2=tail2->next;
            }
            cur=cur->next;            
        }
        tail1->next=head2->next;      //将两个链表合并
        tail2->next=NULL;

        struct ListNode* head=head1->next;
        free(head1);
        free(head2);
        return head;                  //最后返回链表1的第一个节点
    }

2. 题目二:相交链表

题目描述:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

 示例:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

 题目链接:

相交链表https://leetcode.cn/problems/intersection-of-two-linked-lists/description/

2.1 思路

        这道题目的解题思路就简单了,但要注意链表长度不同的情况。当两个节点的节点个数不相同时,指向长链表的指针要先走它们节点个数的差值步。然后开始一一对比,直到遇到相交节点为止。

2.2 分析

        链表相交并不是像直线那样交叉相交,单链表中,一个节点只能指向一个节点,所有这里的链表相交是如下图的情况:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

 总体分 3 步:

  • 先遍历两个链表得到两个链表的长度。
  • 长的链表先走差距步(len1-len2)。
  • 开始遍历两个数组,直到相交点,返回相交的节点

2.3 题解

整理完思路后,根据分析的思路进行编写代码:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    struct ListNode* curA=headA,*curB=headB;
    int lenA=1,lenB=1;
    while(curA->next)
    {
        curA=curA->next;
        lenA++;
    }
    while(curB->next)
    {
        curB=curB->next;
        lenB++;
    }
    if(curA!=curB)        //如果遍历到最后两个链表的尾节点不是同一个节点就说明不相交。
    {
        return NULL;
    }
    int t= abs(lenA-lenB);//求出差距步  abs是求绝对值的函数
    struct ListNode* longlist=headA, *shortlist=headB;
    if(lenB>lenA)           //这里先假设链表A长,如果不是链表A长就交换一下,简化代码
    {
        longlist=headB;
        shortlist=headA;
    }
    while(t--)              //长的链表走差距步
    {
        longlist=longlist->next;
    }
    while(longlist!=shortlist)//两链表同时遍历
    {
        longlist=longlist->next;
        shortlist=shortlist->next;
    }
    return longlist;          //循环停止时指向的节点就是第一个相交节点,返回它们两个任意一个
}

3. 题目三:环形链表

题目描述:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

 示例:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

 题目链接:

环形链表https://leetcode.cn/problems/linked-list-cycle/description/

3.1 思路

         我们知道循环链表,循环链表的尾指向链表的头,遍历一遍之后会回到链表的头,但这道题属于带环链表,带环链表的尾不一定连接着头,它可能连接着任意节点。带环链表的题目属于链表中较为复杂的题目,那要如何判断一个链表是否带环呢?

        首先我们知道,带环链表在向后遍历的时候,一定会回到入环点,比较链表中的节点是否为入环时的节点就可以了,但是问题来了,我们怎么知道哪个是开始入环的节点?不知道入环的节点又怎么比较是否是同一个节点。显然传统的思路行不通,那我们就来换一种方法。

        这里我们就可以使用快慢指针的方法,一个指针走的快一个指针走的慢,当快的指针再次与慢指针相遇,那就说明这个链表一定是带环链表。

3.2 分析

        带环链表的入环节点可能是任意节点:

数据结构刷题训练——链表篇(二),数据结构刷题训练营,数据结构,链表,c语言,算法,leetcode,经验分享

         它也可以指向它自己。

        这里我们可以使用快慢指针的方法,使用快指针来追击慢指针,当快指针与慢指针再次相遇,这就说明这个链表一定为带环链表,但是如果快指针走到了NULL,这就说明这个链表不是带环链表。

3.3 题解

 根据分析的思路,我们整理一下,形成代码:

bool hasCycle(struct ListNode *head) {
    struct ListNode* fast,*slow;
    fast=slow=head;
    while(fast&&fast->next)
    {
        
        slow=slow->next;
        fast=fast->next->next;
        if(fast==slow)
        {
            return true;
        }
        
    }
    return false;
}

         题解也是非常简单。对于带环链表,今天这道题目属于热身,下期我会专门出一期带环链表的题目。


 

总结

        最后,感谢你的阅读和支持。希望你在这个数据结构的学习旅程中能够获得满满的收获和成就感。愿我们共同努力,不断探索和挑战,成为数据结构领域的行家里手!文章来源地址https://www.toymoban.com/news/detail-631483.html

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

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

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

相关文章

  • 数据结构刷题训练——二叉树篇(一)

    📙 作者简介:  清水加冰,目前大二在读,正在学习C/C++、Python、操作系统、数据库等。 📘 相关专栏: C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误还望各路大佬指正! ✨每一次努力都

    2024年02月07日
    浏览(40)
  • 数据结构刷题训练:设计循环队列(力扣OJ)

    目录 文章目录 前言 1. 题目:设计循环队列 2. 思路 3. 分析  3.1 定义循环队列  3.2 创建队列  3.3 判空和判满  3.4 入队  3.5 出队  3.6 取队头队尾数据  3.7 销毁队列  4. 题解 总结         当谈到队列数据结构时,很多人可能会想到普通的队列,即先进先出(FIFO)的数据结

    2024年02月13日
    浏览(35)
  • 趣说数据结构(练习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日
    浏览(27)
  • 数据结构刷题训练:用栈实现队列(力扣OJ)

    目录 前言 1. 题目:用栈实现队列 2. 思路 3. 分析  3.1 定义 “ 队列 ”  3.2 创建队列 3.3 入队  3.4 队头数据  3.5 出队  3.6 判空和销毁 4.题解 总结         栈和队列是数据结构中的两个重要概念,它们在算法和程序设计中都有着广泛的应用。本文将带你深入了解如何使用

    2024年02月13日
    浏览(29)
  • 【算法刷题之链表篇(2)】

    给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中,返回合并后的链表。 思路 : 首先写出合并两个链表的代码 : 1.定义两个指针分别位于两个链表的头处,再定义一个哨兵位用于接受元素; 2.两个链表头处的指针开始遍历,并且相互

    2024年02月11日
    浏览(25)
  • 【算法刷题之链表篇(1)】

    给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。 1.我们从指针 prev 指向链表的哑节点,随后开始对链表进行遍历。 2.如果当前 cur与 cur.next对应的元素相同,那么我们就需要将 cur 以及所有后面拥有相同元素值

    2024年02月12日
    浏览(23)
  • 数据结构之顺序表篇

    一、顺序表概念 二、顺序表各类接口实现 *顺序表初始化 **顺序表销毁 ***顺序表插入操作 ****顺序表删除操作 *****顺序表查找操作 ******顺序表实现打印操作 三、顺序表整体实现源码 *SeqList.h **SeqList.c ***test.c 讲顺序表之前先引入线性表概念,线性表是n个有相同特性的数据元素

    2024年02月02日
    浏览(25)
  • LeetCode刷题系列之----->(指针玩转链表篇)(三)

    🍉博客主页:阿博历练记 📖文章专栏:数据结构与算法 🔍代码仓库:阿博编程日记 🌹欢迎关注:欢迎友友们点赞收藏+关注哦 现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后

    2024年02月04日
    浏览(27)
  • 算法刷题营【Day3】:: 链表篇:单链表结点删除思路:一题辨别哨兵结点的优势(删除有奇效):203. 移除链表元素

    本内容是笔者结合《代码随想录》总结所得,记录学习过程,分享知识! 目录: 1. 开篇例题:203. 移除链表元素 2. 题解参考 - - 2.1 方法一:原表操作(不含哨兵结点) - - 2.2 方法二:虚设哨兵结点辅助法 - - 2.3 方法三:递归法 3. 单链表结点删除思路 4. 方法思路点拨:原表操

    2024年02月06日
    浏览(36)
  • 数据结构-链表结构-双向链表

    双向链表也叫双链表,与单向链表不同的是,每一个节点有三个区域组成:两个指针域,一个数据域 前一个指针域:存储前驱节点的内存地址 后一个指针域:存储后继节点的内存地址 数据域:存储节点数据 以下就是双向链表的最基本单位 节点的前指针域指向前驱,后指针

    2024年02月04日
    浏览(36)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包