考前一笔——私と链表の奇妙な物語

本文讲述了作者在学习C语言过程中,特别是链表部分的经历转变,从最初的畏惧到逐渐理解其灵活性和挑战性,通过解决LeetCode上的问题深化理解。

一个学期与C这门语言的高频次约会,发生了很多,其中印象最深,感触最深的,莫过于链表。

        人的体质不能一概而论啊,对于我而言,自学完C语言整个体系,只有链表,令我望而生畏,指来指去的next,总觉得短短几行,互相指代,瞬息之间千变万化。

        考前写篇文章,谨以此文对C语言学习,对自我与链表作阶段性总结。


一、梦开始的地方

        在一个风雨交加,夜深人静的夜晚,我浅学了链表的相关知识,在若干次乏味地重复的操作CreateNode,InsertNode,CreateList,InsertList……之后,我在LeetCode上看到这样两道题

力扣and力扣

        分别是“奇偶链表”和“分隔链表”,这两题做法都非常相似,如果站在暴力的角度上,创建两个新的链表头,一次遍历原链表,将链表中每一个节点归入两个队列,然后拼接两个队列即可。其中值得注意的是,创建哑结点(可有可无),暂存链表头链表尾拼接以及补NULL

        类似于这样的题目还有力扣的“分割链表”,纯纯的模板,纯纯的套用,梦从此开始夢はこれから始まる。下附力扣第86题分隔链表0ms、5.8MB的AC源代码。

struct ListNode* partition(struct ListNode* head, int x)
{
    struct ListNode*smm=(struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode*laa=(struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode*sm=smm;
    struct ListNode*la=laa;
    while(head)
    {
        if(head->val<x)
        {
            smm->next=head;
            smm=smm->next;
        }
        else
        {
            laa->next=head;
            laa=laa->next;
        }
        head=head->next;
    }
    laa->next=NULL;
    smm->next=la->next;
    return sm->next;
}

二、畏惧——直面——探索

        梦已经开始了,链表这玩意,越接触越发觉得,有趣,太有趣了,指来指去是对不定长数据的定期维护,相比于数组,链表极具灵活性。

        链表与数组相似,翻转、排序、筛选、引用、拼接……

        为此,在筛选方面,果然没让人失望捏,在想着要练点什么之前,贴心的LeetCode已经准备好了力扣 “19. 删除链表的倒数第 N 个结点”、力扣82. 删除排序链表中的重复元素 II”、力扣83. 删除排序链表中的重复元素

        链表没有寻址访问中间元素的功能,这一特殊性导致各种查找和筛选只能依赖于一次遍历,于是就出现了各种意义上的:备份表头,遍历,备份表头,连接。不得不说,经历这些之后,对链表更加又爱又恨,爱在每一次征服的自豪,恨在稍不留神的炸内存,各种内存访问越界。

        下附力扣“82.删除排序链表中的重复元素”:4ms、6.2MB 的AC代码,主要思路在于备份当前结点比较下一个结点和下下个结点,必要时继续往后,直到找到可以重新建立链接的下一个结点。当找到前一个结点不等于后一个结点时,需要标记这个不同的元素,继续向后找,避免出现前后都是需要删除的元素的情况。这一点我在做题的时候也是思考了很久,如何规避这样的情况。

struct ListNode* deleteDuplicates(struct ListNode* head)
{
    struct ListNode*res=(struct ListNode*)malloc(sizeof(struct ListNode));
    res->next=head;
    res->val=0;
    struct ListNode*cur=res;
    while(cur->next&&cur->next->next)
    {
        if(cur->next->val==cur->next->next->val)
        {
            int x=cur->next->val;
            while(cur->next&&cur->next->val==x)
            {
                cur->next=cur->next->next;
            }
        }
        else
        {
            cur=cur->next;
        }
    }
    return res->next;
}

三、上头,上头,还是上头

        力扣中链表这方面我的练习进度是32/100,以后在C++接触树系列之后感触应该会更深刻,就学习到现在,起初对链表的恐惧已经不复存在了,越是学习,越是想了解更多,掌握更多,C已至此,攻克链表,这学期也结束了,但是编程永无止境,以后我还将会维持一定的发文节奏,尽我所能写出向之前一样可以突破7000阅读的文章《表示数字的最少运算符》,这类优质的文章。

        来日方长,学习永无止境。

        最后来点“《独立宣言》”:我可是立志要成为优秀码农的男人!

        阶段性总结至此封笔。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值