数据结构——图解链表OJ题目

news2025/1/9 15:22:55

        学完了单链表之后,我们对其基本结构已经有了一定的了解,接下来我们通过一些题目强化对链表的理解,同时学习一些面试笔试题目的新思路以及加强对数据结构单链表的掌握。 


目录

题目一.876. 链表的中间结点 - 力扣(LeetCode)

题目二:21. 合并两个有序链表 - 力扣(LeetCode)

题目三:203. 移除链表元素 - 力扣(LeetCode)

题目四: 206. 反转链表 - 力扣(LeetCode)

题目五:141. 环形链表 - 力扣(LeetCode)

题目六: 142. 环形链表 II - 力扣(LeetCode)


题目一.876. 链表的中间结点 - 力扣(LeetCode)

  • 给你单链表的头结点 head ,请你找出并返回链表的中间结点。
  • 如果有两个中间结点,则返回第二个中间结点。

我们一起来思考一下这道题目:返回链表的中间结点。我们先来了解一种新思路:快慢指针!我们定义两个指针:一个快指针,一个慢指针。每次快指针走两步,慢指针走一步。我们来看一下演示过程:

一个中间结点情况:

两个中间结点情况:

通过演示过程我们可以清楚的看到:

  • 如果是奇数结点,当fast指向尾结点,slow返回中间结点。
  • 如果是偶数结点,当fast指向空时(越过尾结点),slow返回中间结点。

总结以上规律,应在当 fast遇到或越过尾节点时跳出循环,并返回 slow 即可。

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

题目二:21. 合并两个有序链表 - 力扣(LeetCode)

  • 将两个升序链表合并为一个新的 升序 链表并返回。
  • 新链表是通过拼接给定的两个链表的所有节点组成的。

我们要返回一个升序的新链表,那么我们可以借助一个头指针,将list1和list2进行比较,值小的尾插放入新的链表中,再用头指针指向新的链表就可以。

在题目中注意判断list1为空,list2为空是怎么办?

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    struct ListNode*head=NULL,*tail=NULL;
    // 处理特殊情况
    if(list1==NULL)
        return list2;
    if(list2==NULL)
        return  list1;

    while(list1&&list2)
    {
        if(list1->val<list2->val)
        {
            if(tail==NULL)
                tail=head=list1;
            else
            {
                tail->next=list1;
                tail=tail->next;
            }
            list1=list1->next;
        }
        else
        {
            if(tail==NULL)
                tail=head=list2;
            else
            {
                tail->next=list2;
                tail=tail->next;
            }
            list2=list2->next;
        }
    }
    if(list1)
        tail->next=list1;
    if(list2)
        tail->next=list2;

    return head;
}

题目三:203. 移除链表元素 - 力扣(LeetCode)

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

思路一:我们定义一个指针,让这个指针移动从而去寻找链表中和val相等的值,要是遇到就把它释放掉,然后把上一个结点和释放掉后的下一个结点连接起来,最后返回头结点head就可以。但这个思路有什么问题我们想一想?如果头结点就需要释放呢,那我们就要把返回的头结点此时后移,注意考虑这个情况!

大家可以自己思考一下,再参考下面代码。

struct ListNode* removeElements(struct ListNode* head, int val) {
    struct ListNode*prev=NULL,*cur=head;
    while(cur)
    {
        if(cur->val==val)
        {
            if(cur==head)
            {
                head=cur->next;
                free(cur);
                cur=head;//cur=head->next错误
            }
            else
            {
                prev->next=cur->next;
                free(cur);
                cur=prev->next;
            }
        }
        else
        {
            prev=cur;
            cur=cur->next;
        }
    }
    return head;
}

思路二:我们定义一个新的结点,当指针指向的值不等于val值的时候,把结点连接到新结点上。这样返回的新的头结点就是一个没有val值的链表。

大家可以自己思考一下,再参考下面代码。

struct ListNode* removeElements(struct ListNode* head, int val) {
    struct ListNode* cur=head;
    struct ListNode* tail=NULL,*newnode=NULL;

    while(cur)
    {
        if(cur->val==val)
        {
            struct ListNode* node=cur;
            cur=cur->next;
            free(node);
        }
        else
        {
            if(tail==NULL)
            {
                newnode=tail=cur;
            }
            else
            {
                tail->next=cur;
                tail=tail->next;
            }
            cur=cur->next;
        }
    }
    if(tail)
        tail->next=NULL;

    return newnode;
}

题目四: 206. 反转链表 - 力扣(LeetCode)

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

还记得之前写的线性表头插吗?我们发现头插和输入的顺序刚好相反,那我们把这个思想用在这道题目上,我们把链表的值头插到新的一个链表中,返回头插后的链表的头结点。

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;
}

题目五:141. 环形链表 - 力扣(LeetCode)

  • 给你一个链表的头节点 head ,判断链表中是否有环。
  • 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
  • 如果链表中存在环 ,则返回 true 。 否则,返回 false 。

这个题目超级有意思,检查链表里有没有环,还记得我们的快慢指针吗?如果有环的话,快指针肯定先入环,慢指针如果在环中和快指针相遇了,说明有环;如果没有相遇,说明无环。

大家肯定有一个问题:为什么有环就一定可以追上,我们一起分析一下。当slow进环后,fast开始追击,假设它们之间的距离为N,那么走一次,它们之间的距离变为N-1,下一次为N-2,N-3,......3,2,1,0,最后它们之间的距离就是0。所以只要有环,它们一定会相遇。

bool hasCycle(struct ListNode *head) {
    struct ListNode* slow=head,*fast=head;

    while(fast&&fast->next)//快指针将到达链表尾部,该链表不为环形链表
    {
        slow=slow->next;
        fast=fast->next->next;

        if(slow==fast)
            return true;

    }
    return false;
}

题目六: 142. 环形链表 II - 力扣(LeetCode)

  • 给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
  • 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

这个题目其实有点数学题的意思,我们来分析一下:假设起点到入口点的距离是L,环的周长是C,入口点到相遇点距离是X,我们已经分析过,slow进环后一圈内,fast必追上slow,那么slow的距离就是:L+X,fast的距离是L+n*C+X,L可能很长,导致fast已经在环里走路不止一圈,slow才进入,所以fast是n*C,那么我们已知fast走的距离是slow的两倍,这是快慢指针的定义,所以我们列出式子:2(L+X)=L+n*C+X,解出L=(n-1)*C+C-X.也就是说,一个指针从起点走,另一个从相遇点走,他们会在入口点相遇。

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* slow,*fast;
    slow=fast=head;

    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;

        if(slow==fast)
        {
            struct ListNode* meet=slow;

            while(head!=meet)
            {
                meet=meet->next;
                head=head->next;
            }

            return meet;
        }
    }
    
    return NULL;
}

今天的分享就到这里,大家有哪里不懂的可以私信我,或在评论区讨论,大家可以把这些题目作为链表的练习题目,希望对大家的编程和数据结构有帮助! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1275204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

金蝶云星空单据界面新增状态,操作明细行的新增按钮时判断表头基础资料是否必录

文章目录 金蝶云星空单据界面新增状态&#xff0c;操作明细行的新增按钮时判断表头基础资料是否必录BOS配置代码实现 金蝶云星空单据界面新增状态&#xff0c;操作明细行的新增按钮时判断表头基础资料是否必录 BOS配置 四种方式都不生效。 代码实现 表单插件的BeforeDoOpera…

最短路算法

文章目录 最短路总览朴素Dijkstra - 稠密图 - O ( n 2 ) O(n^2) O(n2)具体思路时间复杂度分析使用场景AcWing 849. Dijkstra求最短路 ICODE 堆优化 D i j k s t r a Dijkstra Dijkstra 算法 - 稀疏图 - O ( m l o g n ) O(mlogn) O(mlogn)具体思路和时间复杂度分析使用场景A…

九章量子计算机:引领量子计算的新篇章

九章量子计算机:引领量子计算的新篇章 一、引言 随着科技的飞速发展,量子计算已成为全球科研领域的前沿议题。九章量子计算机作为中国自主研发的量子计算机,具有划时代的意义。本文将深入探讨九章量子计算机的原理、技术特点、应用前景等方面,带领读者领略量子计算的魅力…

11.28~11.29基本二叉树的性质、定义、复习;排序算法;堆

完全二叉树&#xff08;Complete Binary Tree&#xff09;是一种特殊的二叉树结构&#xff0c;它具有以下特点&#xff1a; 所有的叶子节点都集中在树的最后两层&#xff1b;最后一层的叶子节点都靠左排列&#xff1b;除了最后一层&#xff0c;其他层的节点数都达到最大值。 …

短剧行业@2023:狂飙、刹车与新生

【潮汐商业评论/原创】 “豪门复仇”“先婚后爱”“重生”“穿越”&#xff0c;Ashley几乎每次回家路过保安亭&#xff0c;都能看到大叔在看这类上头小短剧&#xff0c;就连有时候在公司&#xff0c;也能听到保洁阿姨在看类似的视频。 久而久之&#xff0c;从好奇到“入坑&am…

利用ElementUI配置商品的规格参数

商品有不同的规格组合&#xff0c;自动生成对应规格的所有组合&#xff0c;并设置该规格的图片、价格、库存数据。 <template><div class"sku-list"><template v-if"!disabled"><div class"sku-list-head"><el-but…

Zigbee—基于Z-STACK组网

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;チノカテ—ヨルシカ 0:46━━━━━━️&#x1f49f;──────── 4:08 &#x1f504; ◀️ ⏸ ▶️ ☰ &a…

nginx配置反向代理及负载均衡

目录 1.前端发送的请求&#xff0c;是如何请求到后端服务的1.nginx 反向代理的好处&#xff1a;2.nginx 反向代理的配置方式&#xff1a;3. nginx 负载均衡的配置方式 1.前端发送的请求&#xff0c;是如何请求到后端服务的 1.nginx 反向代理的好处&#xff1a; 提高访问速度 因…

如何使用 NFTScan NFT API 在 Starknet 网络上开发 Web3 应用

Starknet 是由以色列软件公司 StarkWare 开发的免许可的第 2 层网络。Starknet 作为以太坊上的 ZK Rollup 运行&#xff0c;帮助 dApp 使用 STARK 证明以更低的交易成本实现更大的计算规模。该网络允许智能合约与区块链上部署的其他合约进行交互&#xff0c;从而提高协议之间的…

大数据Doris(三十一):Doris简单查询

文章目录 Doris简单查询 一、简单查询 二、​​​​​​​Join

基于Springboot的在线问卷调查系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的在线问卷调查系统(有报告)。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring…

golang WaitGroup的使用与底层实现

使用的go版本为 go1.21.2 首先我们写一个简单的WaitGroup的使用代码 package mainimport ("fmt""sync" )func main() {var wg sync.WaitGroupwg.Add(1)go func() {defer wg.Done()fmt.Println("xiaochuan")}()wg.Wait() }WaitGroup的基本使用场…

Peter算法小课堂—差分与前缀和

差分 Codeforces802 D2C C代码详解 差分_哔哩哔哩_bilibili 一维差分 差分与前缀和可以说成减法和加法的关系、除法和乘法的关系、积分和微分的关系&#xff08;听不懂吧&#xff09; 给定数组A&#xff0c;S为A的前缀和数组&#xff0c;则A为S的差分数组 差分数组构造 现…

Unittest(1):unittest单元测试框架简介setup前置初始化和teardown后置操作

unittest单元测试框架简介 unittest是python内置的单元测试框架&#xff0c;具备编写用例、组 织用例、执行用例、功能&#xff0c;可以结合selenium进行UI自动化测 试&#xff0c;也可以结合appium、requests等模块做其它自动化测试 官方文档&#xff1a;https://docs.pytho…

opencv 图像边框

cv.copyMakeBorder() 图像设置边框或者填充

HarmonyOs 4 (一) 认识HarmonyOs

目录 一 HarmonyOs 背景1.1 发展时间线1.2 背景分析1.2.1 新场景1.2.2 新挑战1.2.3 鸿蒙生态迎接挑战 二 HarmonyOS简介2.1 OpenHarmony2.2 HarmonyOS Connect2.3 HarmonyOS Next**2.4 ArkTS &#xff08;重点掌握&#xff09;****2.5 ArkUI** 三 鸿蒙生态应用核心技术理念**3.…

c/c++概念辨析-指针常量常量指针、指针函数函数指针、指针数组数组指针

概念澄清&#xff1a; 统一规则&#xff1a; 不管是XX指针&#xff0c;还是指针XX&#xff0c;后者是本体&#xff0c;前者只是个定语&#xff0c;前者也可以替换为其他同类&#xff08;例如字符串&#xff09;&#xff0c;帮助理解。 XX指针&#xff1a; 可简单理解为&#…

骨传导耳机是智商税吗?骨传导耳机是利用什么原理听歌?

骨传导耳机并非智商税&#xff0c;而是一种新兴的技术产品。作为是一种新型的听音设备&#xff0c;它采用了与传统耳机不同的工作原理&#xff0c;通过将声音通过骨骼传导到内耳&#xff0c;实现了不用堵塞耳道就能听到声音的效果。相比传统耳机&#xff0c;骨传导耳机具有一些…

mac本地部署stable-diffusion

下载Homebrew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" ①输入“1”选择中科大版本&#xff0c;然后输入Y(YES)&#xff0c;直接输入开机密码&#xff08;不显示&#xff09;然后回车确认&#xff0c;开始下载 ②…

matlab 基于卡尔曼滤波的GPS-INS的数据融合的导航

1、内容简介 略 25-可以交流、咨询、答疑 2、内容说明 基于卡尔曼滤波的GPS-INS的数据融合的导航 "基于卡尔曼滤波的GPS-INS的数据融合的导航 基于卡尔曼滤波实现GPS-INS组合导航系统" 卡尔曼滤波、GPS、INS、数据融合、导航 3、仿真分析 4、参考论文 略 …