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

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

目录

前言

题目一:链表的中间节点

思路

分析

题解

 题目二:链表中倒数第k个结点

思路

分析

 题解

题目三:合并两个有序链表

思路

分析

题解

 方法二

题解

 题目四:链表的回文结构

思路

分析

题解

总结


前言

        今天我将开启一个新的专栏,数据结构与算法刷题训练营,题目从基础简单题目开始逐步进阶,以便于初学者巩固和运用所学的知识。


题目一:链表的中间节点

 题目描述:数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 示例与提示:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 题目链接

链表的中间节点https://leetcode.cn/problems/middle-of-the-linked-list/description/

 思路

        题目中的链表属于单链表,我们要怎么计算中间节点呢?先遍历一遍链表统计链表节点个数,然后计算出中间节点,再遍历到需要返回的节点。这或许是大多数人能想到的方法。但是这种方法效率太低。今天我向大家介绍一种新的做题思路,这种方法在其他题目中也是适用。

快慢指针法:

        我们可以创建两个指针,一个快指针一次走两步,一个慢指针一次走一步。当快指针走到尾时,返回慢指针就是中间节点。

分析

情况一:

节点为奇数个。

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         假设节点有5个,那需要返回的节点就是第3个节点。初始时,两指针都指向第一个节点,慢指针一次走一步,快指针一次走两步。执行一次情况如上图。当快指针走到最后一个节点时就要结束如下图:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 情况二:

节点为偶数个。

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         这是已经执行两次后的状态,接下来fast指针继续走:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         fast指向NULL,而slow指向要返回的节点。

题解

         了解完整体思路,我们依据分析中的情况进行编写代码:

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* fast=head,*slow=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;

}

 数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 题目二:链表中倒数第k个结点

 题目描述:数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 题目链接

倒数第k个节点https://www.nowcoder.com/practice/529d3ae5a407492994ad2a246518148a?tpId=13&&tqId=11167&rp=2&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking

思路

         这道题目依然可以使用快慢指针的方法来寻找倒数第k个节点。先让快指针走k步,然后让两指针同时向后移动,知道快指针遍历完链表结束。

分析

         初始情况下,两指针都指向第一个节点,先让fast指针走k步:

        我们假设要找倒数第3个节点,fast走3步就指向了第四个节点。

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         然后两指针开始同时移动:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         当fast指针指向NULL时就结束,此时slow指向的就是倒数第k个节点。

 题解

 根据上述的分析,我们进行编写代码:

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    struct ListNode* fast=pListHead,*slow=pListHead;
    
        
    for(int i=0;i<k;i++)
    {
        if(fast==NULL)
        {
            return NULL;
        }
        fast=fast->next;
    }
    while(fast)
    {
        fast=fast->next;
        slow=slow->next;
    }
    return slow;
}

        在代码实现时要注意特殊情况,如果链表为NULL或者k大于链表长度,传进来就要进行特殊处理。

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

题目三:合并两个有序链表

 题目描述:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 示例:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 题目链接:

合并两个有序链表https://leetcode.cn/problems/merge-two-sorted-lists/description/

思路

        题目中给的是升序数组,解题思路就是比较链表元素,取小的进行尾插。思路较为简单。

分析

 接下来我们对整体规划进行分析假设初始时:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         把一个链表的元素插入到另一个链表这样操作太麻烦,所以我们可以重新创建一个头指针,将两个链表上的节点插入到新的链表中,创建新链表时,初始化头和尾都为NULL。

 数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         然后进行比较,第一步两个大小相同,任取一个插入:

 数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         然后再拿着list2中的第一个节点与list1节点进行比较,插入:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         以此类推不断进行比较尾插。

 数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

        结束条件就是一个链表为NULL结束 

 数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         最后将剩余节点的链表尾插到新链表中,返回新链表的头。

题解

        理解了思路就根据分析的内容进行编写代码:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if(list1==NULL)                //考虑原链表中有空链表的情况。
        return list2;
    if(list2==NULL)
        return list1;
    struct ListNode* head=NULL,*tail=NULL;
    while(list1&&list2)
    {
        if(list1->val > list2->val)//比较大小取小的尾插
        {
            if(head==NULL)         //考虑特殊情况新建链表为NULL时进行特殊处理
            {
                tail=head=list2;
                
            }
            else                   //尾插
            {
                tail->next=list2;
                tail=tail->next;
            }
            list2=list2->next;    //尾插后继续向后
        }
        else
        {
             if(head==NULL)
            {
              tail=head=list1;
               
            }
           else
           {
                tail->next=list1;
                tail=tail->next;
           }
           
            list1=list1->next;
        }
    }
    if(list2==NULL)            //一个链表为NULL时将另一个链表剩余的节点尾插到新链表。
        tail->next=list1;
    else
        tail->next=list2;
    return head;
}

 虽然思路非常简单,但是代码实现却很不容易,需要很多要考虑的特殊情况。

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表 

 方法二

        和思路一相同,也是比较大小,将小的尾插到新的链表。但是可以使用带头结点的链表,这样再插入时就不需要考虑新链表为NULL时的情况,进行特殊处理。可以更好的简化代码。

题解

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if(list1==NULL)
        return list2;
    if(list2==NULL)
        return list1;
    struct ListNode* head=NULL,*tail=NULL;
    head=tail=(struct ListNode*)malloc(sizeof(struct ListNode));
    while(list1&&list2)
    {
        if(list1->val > list2->val)
        {
           
            
            tail->next=list2;
            tail=tail->next;
            list2=list2->next;
        }
        else
        {
             
            tail->next=list1;
            tail=tail->next;
           
            list1=list1->next;
        }
    }
    if(list2==NULL)
        tail->next=list1;
    else
        tail->next=list2;
    struct ListNode* del=head;
    head=head->next;
    free(del);
    return head;
}

         注意:原链表中不带头节点,返回时不能返回头节点,需要将头节点释放掉,返回头节点的下一个节点。

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 

 题目四:链表的回文结构

题目描述:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 题目链接:

链表的回文结构https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId=49&&tqId=29370&rp=1&ru=/activity/oj&qru=/ta/2016test/question-ranking

思路

        有人可能会想,这不很简单吗?把这个链表反转一下,再和原链表数据依次比较不就解决了,但是这里注意题目要求。

        题目要求时间复杂度为O(N),空间复杂度为O(1),上述思路需要将原链表复制一份后才可以与逆置是链表进行比较,空间复杂度为O(N)。

        这道题的思路是这样的,可以先找到链表的中间节点,然后从中间节点开始,对后部分的链表进行逆置,然后从中间开始与开头的节点对比,看两个值是否相同。

分析

 情况一:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         节点为偶数个,把后半部分节点逆置,然后依次比较,这里注意其实前半部分的2节点的next这时依然指向的是后半部分的2,后半部分的2节点的next指向NULL。如下图:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 逆置之后,返回的是后半部分1节点的地址,然后进行遍历,直到为NULL结束。

情况二:

        节点数量为奇数个

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

 实际情况和上述一样:

数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表

         但这里在比较的时候就要注意一下3节点,这里不需要把前半部分2节点的next置为NULL,当遍历到最后时,都遍历到了3节点一定是相同的

题解

        当然这些逆置、找中间节点的接口我们已经写过了,可以CV一下前边的代码,这样写代码还是很舒服的Ctrl+C、Ctrl+V

        当然借此我再介绍一种新的逆置链表的方法,我们可以使用头插来实现链表逆置。将原链表的节点依次头插到新的节点,这样就轻松实现了逆置。

代码如下:

struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* cur=head;
    struct ListNode* newhead=NULL;
    while(cur)
    {
        struct ListNode* next=cur->next;
    //头插
        cur->next=newhead;
        newhead=cur;

        cur=next;
    }
    return newhead;
}

 整体题解:

class PalindromeList {
public:
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* cur=head;
    struct ListNode* newhead=NULL;
    while(cur)
    {
        struct ListNode* next=cur->next;
        cur->next=newhead;
        newhead=cur;

        cur=next;
    }
    return newhead;
}

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* fast=head,*slow=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        
    }
    return slow;
}

    bool chkPalindrome(ListNode* A) {
        struct ListNode* mid=middleNode(A);//中间节点
        struct ListNode* rmid=reverseList(mid);//反转后的中间节点

       while(A && rmid)    
       {
        if(A->val!=rmid->val)
        {
            return false;
        }
        else
        {
            rmid=rmid->next;
            A=A->next;
        }
       }
       return true;
    }
};

 数据结构刷题训练——链表篇(一),数据结构,算法,c语言,链表


 

总结

        好的本期内容到此结束,后续我将会分享更多数据结构相关的题目,通过画图逐步分析,来帮助大家刷题,这些题目建议大家先做一遍,然后看思路与分析,一定要动手敲一敲代码。最后,感谢阅读!文章来源地址https://www.toymoban.com/news/detail-628764.html

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

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

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

相关文章

  • LeetCode 刷题 数据结构 链表 203 移除链表元素

    LeetCode 刷题 数据结构 链表 203 移除链表元素

    Given the  head  of a linked list and an integer  val , remove all the nodes of the linked list that has  Node.val == val , and return  the new head . Example 1: Example 2: Example 3: Constraints: The number of nodes in the list is in the range  [0, 104] . 1 = Node.val = 50 0 = val = 50 今天leetcode的中文官网比较卡,所以是登录官网进行

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

    算法刷题营【Day3】:: 链表篇:单链表结点删除思路:一题辨别哨兵结点的优势(删除有奇效):203. 移除链表元素

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

    2024年02月06日
    浏览(7)
  • 数据结构刷题训练:队列实现栈

    数据结构刷题训练:队列实现栈

    目录 前言 1. 题目:使用队列实现栈 2. 思路 3. 分析  3.1 创建栈 3.2入栈 3.3 出栈 3.4 栈顶数据 3.5 判空和 “ 栈 ” 的销毁  4. 题解 总结         我们已经学习了栈和队列,也都实现了它们各自的底层接口,那么接下我们就要开始栈和队列的专项刷题训练。 题目描述:  题

    2024年02月13日
    浏览(8)
  • 数据结构刷题训练——二叉树篇(一)

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

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

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

    数据结构刷题训练:设计循环队列(力扣OJ)

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

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

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

    数据结构刷题训练:用栈实现队列(力扣OJ)

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

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

    数据结构之顺序表篇

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

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

    LeetCode刷题系列之----->(指针玩转链表篇)(三)

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

    2024年02月04日
    浏览(8)
  • 【算法与数据结构】链表

    【算法与数据结构】链表

    链表是由一串节点串联在一起的,链表的每个节点存储两个信息:数据+下一个节点的地址 分清楚两个概念:什么是内存内部,什么是程序内部 内存内部: 信息存储在内存空间里的 程序内部: 通过什么信息,去操作结构 如果想操作链表的话,我们依靠的是程序内部的信息,

    2024年02月03日
    浏览(12)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包