链表相关OJ

目录

1、移除链表元素

(1)题目描述 

(2)算法原理 

2、链表的中间结点

(1)题目描述

(2)算法原理 

3、链表中倒数第K个结点 

(1)题目描述 

(2)算法原理 

4、反转链表

(1)题目描述

(2)算法原理

5、合并两个有序链表

 (1)题目描述

(2)算法原理

6、分割链表 

(1)题目描述

(2)算法原理

7、回文链表 

(1)题目描述

(2)算法原理 

8、链表相交

(1)题目描述

(2) 算法原理

9、环形链表

(1)题目描述

(2)算法原理 

10、环形链表ll

(1)题目描述

(2)算法原理


1、移除链表元素

203. 移除链表元素 - 力扣(LeetCode)

(1)题目描述 

(2)算法原理 

解法一:尾插到新链表

当我们看到这道题的时候,我相信大多数人脑海中的第一个想法就是直接尾插到一个新链表当中。因此,我们可以遍历这个链表,如果当前节点的val不是要删除的数,就将它尾插到新链表 ,最后返回新链表的头。

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution 
{
public:ListNode* removeElements(ListNode* head, int val) {if(head == nullptr)return nullptr;ListNode* newhead = nullptr, *tail = nullptr;ListNode* cur = head;while(cur){//如果不是要删除的val,就尾插if(cur->val != val){//刚开始newhead为空,需要特殊处理。if(newhead == nullptr){newhead = tail = cur;}//尾插else {tail->next = cur;tail = tail->next;}}cur = cur->next;}if(tail)tail->next = nullptr;return newhead;}
};

这个地方还是有细节需要注意的, 在最后需要把tail的next置为空。这里tail是有可能为空的,如果为空的话就会报错。因此需要特判一下。比如说题目给的示例3,链表里的数全是7,要删除的也全是7,此时就不会进入尾插的逻辑,tail就是空的。

这种做法是可以解决这道题的,但是毕竟不是真正的删除。因此接下来我们考虑一下如何在原链表上进行删除。

解法二:双指针

我们先看用一个指针行不行,肯定是不行的,因为你需要更改链接关系,还要删除,一个指针肯定是不行的,因此我们需要一个前驱指针,帮助我们修改链接关系。

开始的时候让prev为空,cur为头节点, 然后遍历链表,如果cur节点的值不是要删除的值,就让prev更新为cur,cur=cur->next。否则说明cur节点的值是要删除的值,此时直接更新prev的指向关系,让prev的next指向cur的next,然后删除cur,在把cur更新为prev的next,prev和cur始终保持以前一后的关系。这里要注意一种情况,就是说我一上来第一个节点就是要删除的,那么这个时候prev是空呀,那么就会出问题,因此要特殊处理prev为空的情况,如果为空,说明一上来就是要删除的节点,那么此时将head更新为cur的下一个节点,然后删除cur,再将cur更新为head即可。prev不用动。

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution 
{
public:ListNode* removeElements(ListNode* head, int val) {ListNode* prev = nullptr;ListNode* cur = head;while(cur){if(cur->val != val){prev = cur;cur = cur->next;}else {if(prev == nullptr){head = cur->next;delete cur;cur = head;}else{prev->next = cur->next;delete cur;cur = prev->next;}}}return head;}
};

2、链表的中间结点

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

(1)题目描述

(2)算法原理 

解法一:暴力求解

这道题大多数人看到之后的第一想法就是,我先遍历一遍这个链表,统计一下节点个数,然后节点个数除以2,然后再遍历一遍链表,就可以得到答案。

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution 
{
public:ListNode* middleNode(ListNode* head) {int count = 0;ListNode* cur = head;while(cur){count++;cur = cur->next;}count /= 2;cur = head;while(count--){cur = cur->next;}return cur;}
};

解法二:快慢指针

但是这道题有一种非常优秀的解法就是快慢指针。就是搞fast,slow两个指针,一开始都指向头节点,然后fast一次都两步,slow一次走一步,当fast或者fast->next为空的时候,slow刚好就是中间节点。

节点个数为奇数时:

节点个数为偶数时:

代码: 

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution 
{
public:ListNode* middleNode(ListNode* head) {ListNode* slow = head,  *fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;}
};

3、链表中倒数第K个结点 

链表中倒数第k个结点_牛客题霸_牛客网 (nowcoder.com)

(1)题目描述 

(2)算法原理 

解法一:暴力求解

我们第一眼看到这道题的时候肯定是想着先遍历一遍链表,统计链表长度n,然后长度n减去k,之后从头开始走n-k步。这里要注意,链表长度是有可能小于k的,因此要注意处理一下这种情况。

/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}
};*/
class Solution 
{
public:ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {if(pListHead == nullptr)return nullptr;ListNode* cur = pListHead;int count = 0;while(cur){count++;cur = cur->next;}count -= k;if(count < 0)return nullptr;cur = pListHead;while(count--){cur = cur->next;}return cur;}
};

解法二:快慢指针

这道题可以直接用快慢指针,定义slow和fast两个指针,先让fast走k步,然后再让fast和slow同时往后走,当fast走到空的时候,slow就是倒数第K个节点。其实是很好理解的。我们假设链表长度为n,fast先走k步,意味着fast到链表n的距离是n - k,之后slow和fast同时往后走,当fast到达结尾的时候,走的了n-k步,因此slow也就走了n-k步。刚好就是倒数第k个节点的位置。

但是要注意,就是K可能超出了链表的长度。

代码:

class Solution 
{
public:ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {if(pListHead == nullptr)return nullptr;ListNode* fast = pListHead;ListNode* slow = pListHead;while(k--){if(fast)fast = fast->next;elsereturn nullptr;}while(fast){slow = slow->next;fast = fast->next;}return slow;}
};

4、反转链表

206. 反转链表 - 力扣(LeetCode)

(1)题目描述

(2)算法原理

解法一:头插到新链表

利用头插的思想,直接将原链表节点头插到新链表当中。

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution 
{
public:ListNode* reverseList(ListNode* head) {ListNode* newhead = nullptr;ListNode* cur = head;while(cur){ListNode* next = cur->next;cur->next = newhead;newhead = cur;cur = next;}return newhead;}
};

解法二:三指针

话不多说,直接上图

代码:

class Solution 
{
public:ListNode* reverseList(ListNode* head) {if(head == nullptr) return nullptr;ListNode* prev = nullptr;ListNode* cur = head;ListNode* next = head->next;while(cur){cur->next = prev;prev = cur;cur = next;if(next)next = next->next;        }return prev;}
};

5、合并两个有序链表

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

 (1)题目描述

(2)算法原理

如果大家做过合并两个有序数组那道题的话,这道题的解法是类似。我们可以同时遍历这两个链表,将val小的尾插到新链表中。当一个链表遍历结束的时候结束循环,之后将另一个尾插到新链表中。

代码:

class Solution 
{
public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {if(list1 == nullptr)return list2;if(list2 == nullptr)return list1;ListNode* newhead = nullptr;ListNode* tail = nullptr;while(list1 && list2){if(list1->val < list2->val){if(newhead == nullptr){newhead = tail = list1;}else{tail->next = list1;tail = tail->next;}list1 = list1->next;}else{if(newhead == nullptr){newhead = tail = list2;}else{tail->next = list2;tail = tail->next;}list2 = list2->next;}}//直接尾插即可。不需要whileif(list1){tail->next = list1;}if(list2){tail->next = list2;}return newhead;}
};

6、分割链表 

 面试题 02.04. 分割链表 - 力扣(LeetCode)

(1)题目描述

(2)算法原理

这道题的思路就是我们搞两个链表small和large,然后遍历原始链表,将小于x的尾插到small,然后大于x的尾插到large,之后把large连接到small后面。这道题最后搞个哨兵位的头结点,写代码的时候就不用处理特殊情况了

代码:

class Solution 
{
public:ListNode* partition(ListNode* head, int x) {ListNode* small = new ListNode(0);ListNode* smallHead = small;ListNode* large = new ListNode(0);ListNode* largeHead = large;while (head != nullptr) {if (head->val < x) {small->next = head;small = small->next;} else {large->next = head;large = large->next;}head = head->next;}large->next = nullptr;small->next = largeHead->next;return smallHead->next;}
};

7、回文链表 

​​​​​​LCR 027. 回文链表 - 力扣(LeetCode)

(1)题目描述

(2)算法原理 

解法一:利用数组+双指针:

当我们看到这道题的时候,我头脑中的第一个想法就是遍历一遍链表,然后把节点的值存到数组里,然后定义两个指针,判断是不是回文。

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution 
{
public:bool isPalindrome(ListNode* head) {vector<int> v;ListNode* cur = head;while(cur){v.push_back(cur->val);cur = cur->next;}int left = 0, right = v.size() - 1;while(left < right){if(v[left] != v[right])return false;left++;right--;}return true;}
}

解法二:中间节点+反转链表 

第一种解法是可以通过的,但是,有点取巧,有没有更优秀的解法呢?我们可以先找到链表的中间节点,然后将链表的后半部分逆置,然后比较前半部分链表和后半部分是否相同。其实就是我们做过的链表的中间节点和反转链表的一个融合。copy一下上两道题的代码。

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* reverseList(ListNode* head) {if(head == nullptr) return nullptr;ListNode* prev = nullptr;ListNode* cur = head;ListNode* next = head->next;while(cur){cur->next = prev;prev = cur;cur = next;if(next)next = next->next;}return prev;}ListNode* middleNode(ListNode* head) {ListNode* fast = head, *slow = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;}bool isPalindrome(ListNode* head) {ListNode* mid = middleNode(head);ListNode* rhead = reverseList(mid);while(rhead){if(head->val != rhead->val)return false;rhead = rhead->next;head = head->next;}return true;}
};

8、链表相交

(1)题目描述

(2) 算法原理

通过观察不难发现我们可以遍历一下链表A和链表B的长度,然后让记录链表A和链表B的长度,之后让长的链表先走差距步,在同时走,如果有相同的节点就说明链表是有交点的。这里要注意不能比值,而要比地址。

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution 
{
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {if(headA == nullptr || headB == nullptr)return nullptr;int len1 = 0, len2 =0;ListNode* cur1 = headA;ListNode* cur2 = headB;//求出链表长度while(cur1){len1++;cur1 = cur1->next;}while(cur2){len2++;cur2 = cur2->next;}//差距步int gap = abs(len1 - len2);//假设headA长ListNode* longg = headA;ListNode* shout = headB;if(len1 < len2){//说明假设错了,更改一下longg = headB;shout = headA;}while(gap--) //长的链表走差距步{longg = longg->next;}while(longg != shout){longg =longg->next;shout = shout->next;}return longg;}
};

9、环形链表

141. 环形链表 - 力扣(LeetCode)

(1)题目描述

(2)算法原理 

先说结论,这道题要用快慢指针。定义slow和fast两个指针,让slow每次走一步,fast每次走两步,如果是环形链表,则一定会有slow==fast。那么问题就来了。

1、为什么slow走一步,fast走两步它们两个会相遇,会不会错过呢?

2、如果slow走1步,fast走n步(n>2),它们两个会相遇? 会错过?

当n为3的时候其实就看距离是奇数还是偶数了,n为4的时候看距离是不是3的倍数,以此类推。

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution 
{
public:bool hasCycle(ListNode *head) {ListNode* slow = head;ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast)return true;}return false;}
};

10、环形链表ll

142. 环形链表 II - 力扣(LeetCode)

(1)题目描述

(2)算法原理

解法一:快慢指针

这道题让我们返回入环时候的第一个点,这道题肯定是和上一道题是有 关联的。我们同样可以用快慢指针,和上一道题一样,求出fast和slow的相遇点,然后在用一个指针从头出发,另一个指针从相遇点出发,当它们的第一个地址相同的节点就是入环的第一个点。同样的我们来证明一下。

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution 
{
public:ListNode *detectCycle(ListNode *head) {ListNode* slow, *fast;slow = fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast){ListNode* meet = slow;while(meet != head){meet = meet->next;head = head->next;}return meet;}}return nullptr;}
};

解法二:转换成链表相交

如果解法一大家有些迷惑,我们可以把它转换成链表相交。同样的,利用快慢指针,找到fast和slow的相遇点,然后将相遇点和相遇点下一个节点断开。然后其实就是两个链表找交点的问题了。

代码: 

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*//*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {if(headA == nullptr || headB == nullptr)return nullptr;int len1 = 0, len2 =0;ListNode* cur1 = headA;ListNode* cur2 = headB;//求出链表长度while(cur1){len1++;cur1 = cur1->next;}while(cur2){len2++;cur2 = cur2->next;}//差距步int gap = abs(len1 - len2);//假设headA长ListNode* longg = headA;ListNode* shout = headB;if(len1 < len2){//说明假设错了,更改一下longg = headB;shout = headA;}while(gap--) //长的链表走差距步{longg = longg->next;}while(longg != shout){longg =longg->next;shout = shout->next;}return longg;}
class Solution 
{
public:ListNode *detectCycle(ListNode *head) {ListNode* fast , *slow;fast = slow = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast){ListNode* meet = slow;ListNode* next = meet->next;meet->next = nullptr;ListNode* cur = head;return getIntersectionNode(next,cur);}}return nullptr;}
};

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ssrf漏洞利用+CTF实例

引发ssrf漏洞的几个函数 file_get_contents() 把整个文件读入一个字符串中&#xff0c;获取本地或者远程文件内容fsockopen() 获得套接字信息curl_exec() 执行一个curl会话&#xff0c;由curl_init()初始化一个新的会话&#xff0c;返回一个curl句柄fopen() 打开文件或者URLre…

【C语言】内存函数详细讲解

文章目录 前言strerror的声明和使用字符串分类函数字符转换函数内存拷贝函数&#xff08;memcpy)memcpy的声明和使用memcpy函数的模拟实现 内存拷贝函数&#xff08;memmove&#xff09;memmove的声明和使用memmove模拟实现 内存比较函数&#xff08;memcmp&#xff09;memcmp的…

如何解决在idea中的hadoop日志错误

在idea中操作hadoop的时候&#xff0c;每次运行代码都会发现有个日志错误&#xff0c;虽然不影响程序运行&#xff0c;但是无法打印日志。这是缺少依赖&#xff0c;和windows上缺少log4j的文件 解决方案&#xff1a; 1、导入slf4j依赖 2、导入hadoop中的log4j文件 1、从hado…

Datawhale X 李宏毅苹果书 AI夏令营 《深度学习详解》第十九章 ChatGPT

19.1 ChatGPT 简介和功能 1、对话框可以输入任何东西 2、可以继续追问 19.2 对于 ChatGPT 的误解 1、第一个误解是 ChatGPT 的回答是罐头讯息 2、另外一个常见的误解是 ChatGPT 的答案是网络搜索的结果 3、那 ChatGPT 真正在做的事情是什么呢&#xff1f;一言以蔽之就是做…

开放式激光振镜运动控制器在Ubuntu+Qt下的文本标刻

开放式激光振镜运动控制器在UbuntuQt下的文本标刻 上节课程我们讲述了如何通过UbuntuQt进行振镜校正&#xff08;详情点击→开放式激光振镜运动控制器在UbuntuQt下的激光振镜校正&#xff09;&#xff0c;本节文本标刻是在振镜校正的前提下实现的。 在正式学习之前&#xff0…

F12抓包08:查看网站Cookie

课程大纲 1、查看Cookie 1. 应用界面查看&#xff1a;按F12进入浏览器的开发者模式 - “应用”&#xff08;Application&#xff09; - Cookie&#xff0c;可查看Cookie并进行增、删、改、查操作。 2. 控制台命令行查看&#xff1a;按F12进入浏览器的开发者模式 - “控制台”&…

2025年第八届计算机图形和虚拟国际会议(ICCGV 2025)即将召开!

2025年第八届计算机图形和虚拟国际会议&#xff08;ICCGV 2025&#xff09;将于2025年2月21-23日在中国成都举行。随着信息技术的飞速发展&#xff0c;计算机图形学与虚拟现实技术正以前所未有的速度重塑着我们的认知世界与交互体验。从沉浸式游戏到精准医疗模拟&#xff0c;从…

坐牢第三十八天(Qt)

1、使用Qt绘画事件处理画一个闹钟 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QPaintEvent>//画画处理事件 #include <QPainter>//画画 #include <QTime> //时间类 #include <QTimer>…

电流互感器电压互感器

一&#xff0c;电流互感器 用途&#xff1a;对信号做精确采样和适当补偿功能&#xff0c;方便对5A以内的交流电进行信号采集。主要作用就是对电流进行测量和取样。 扩展&#xff1a;对应输出模拟交流信号可以调节&#xff0c;可根据电位器&#xff08;调节放大比例&#xff0…

Ali_Yun Port

Ali_Yun Port 云服务器端口

基于云原生向量数据库 PieCloudVector 的 RAG 实践

近年来&#xff0c;人工智能生成内容&#xff08;AIGC&#xff09;已然成为最热门的话题之一。工业界出现了各种内容生成工具&#xff0c;能够跨多种模态产生多样化的内容。这些主流的模型能够取得卓越表现&#xff0c;归功于创新的算法、模型规模的大幅扩展&#xff0c;以及海…

FlinkCDC 3.2.0 新增优点 Pattern Replacement in routing rules

新增优点&#xff1a;Pattern Replacement in routing rules flinkcdc 3.2.0版本相较于3.1.0版本&#xff0c;避免了多表多sink多次写 route 路由的麻烦&#xff0c;类似于统一前后缀的形式多表多sink&#xff0c;通过<>正则&#xff0c;大大减少了书写 官网&#xff1…

【干货分享】Ftrans安全数据交换系统 搭建跨网数据传输通道

安全数据交换系统是一种专门设计用于在不同的网络、系统或组织之间安全地传输数据的软件或硬件解决方案。这种系统通常包含多种安全特性&#xff0c;以确保数据在传输过程中的保密性、完整性和可用性。 安全数据交换系统可以解决哪些问题&#xff1f; 安全数据交换系统主要解…

图分类!!!

deepwalk 使用图中节点与节点的共现关系来学习节点的向量表示。那么关键的问题就是如何来描述节点与节点的共现关系&#xff0c;DeepWalk给出的方法是使用随机游走(RandomWalk)的方式在图中进行节点采样,RandomWalk是一种可重复访问已访问节点的深度优先遍历算法。给定当前访问…

CogView-3-Plus:深度解锁智谱AI的图像生成新力量

一、引言&#xff1a;AI助力创意与效率的全面提升 在如今这个瞬息万变的科技时代&#xff0c;AI大模型早就不是实验室里的“神秘武器”&#xff0c;它们已经实实在在地融入到我们的日常工作中了&#xff0c;尤其是在图像生成和内容创作这块儿&#xff0c;简直是效率神器。只要几…

微软 Power Apps MDA 模型驱动应用解决Image字段查询出来缩略图问题变原图方法(c#+Plugin方式)

微软 Power Apps MDA 模型驱动应用解决Image字段查询出来缩略图问题变原图方法&#xff08;c#Plugin方式&#xff09; 在某些特定的场景中&#xff0c;需要将Image字段中的图片取出来&#xff0c;一般来说直接查询这个字段可以直接取&#xff0c;取出来的就是一个Base64格式的图…

OpenHarmony鸿蒙( Beta5.0)智能窗户通风设备开发详解

鸿蒙开发往期必看&#xff1a; 一分钟了解”纯血版&#xff01;鸿蒙HarmonyOS Next应用开发&#xff01; “非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; “一杯冰美式的时间” 了解鸿蒙HarmonyOS Next应用开发路…

springboot luttuc redis 集成protobuf,手动序列化反序列化

前置需知&#xff1a; 1.本文章和网上大部分博客配置不太一样&#xff0c;各位看官要分析一下自己的需求。集成protobuf 本文章主要是手动调用protobuf的序列化方法&#xff0c;而不是交由springboot 去做&#xff0c;会偏向原生java 使用方式 2.由于为了和公司其他的项目达成…

工业机器人9公里远距离图传模块,无人机低延迟高清视界,跨过距离限制

在科技日新月异的今天&#xff0c;无线通信技术正以未有的速度发展&#xff0c;其中&#xff0c;图传模块作为连接现实与数字世界的桥梁&#xff0c;正逐步展现出其巨大的潜力和应用价值。今天&#xff0c;我们将聚焦一款引人注目的产品——飞睿智能9公里远距离图传模块&#x…

前端Excel热成像数据展示及插值算法

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏:《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 目录 &#x1f4d8; 前言 &#x1f4d8;一、热成像数…