【算法】链表相关

【ps】本篇有 5 道 leetcode OJ。 

一、算法简介

        链表是一种常见的线性数据结构,是一种在物理结构上非连续、非顺序的存储结构,其中的数据元素的逻辑顺序由其中的指针链接次序实现,指针链接的每一个结构体都是一个节点。

        链表的结构多种多样,有单向或双向、带头或不带头、循环或非循环之分。但实际中,最常用的是以下两种组合:

  • 无头单向非循环链表(或称单链表)

  • 带头双向循环链表(或称双向链表)

 【Tips】链表的常用技巧

  • 一定要画图!
  • 引入一个虚拟的头节点,利于处理边界情况、对链表进行各种操作。

  • 不要吝啬空间,大胆定义变量去使用,尤其涉及到插入操作的时候。

  • 快慢双指针,可以对链表判环、找环的入口、找链表中倒数第 n 个节点。

【Tips】链表的常见操作

  •  创建一个新节点
  • 尾插
  • 头插

二、相关例题

1)两数相加

2. 两数相加

.1- 题目解析

        要将两个链表的每个节点中的数相加并放在一个新的链表中,那一定就要构建一个链表,我们可以对这个新链表引入一个头节点,然后直接遍历两个链表进行求和,然后将结果构建出一个新节点尾插入头节点即可。

        特别的,我们单独定义一个变量 t,既保存相加的结果,又记录进位。

.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* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode* newhead=new ListNode(0);ListNode*cur1=l1,*cur2=l2,*prev=newhead;int t=0; //保存求和结果+记录进位while(cur1||cur2||t){//取两个链表的节点进行求和if(cur1){t+=cur1->val;cur1=cur1->next;}if(cur2){t+=cur2->val;cur2=cur2->next;}prev->next=new ListNode(t%10);//取结果的个位t/=10;                        //取进位prev=prev->next;}prev=newhead->next;delete newhead;return prev;}
};

2)两两交换链表中的节点

24. 两两交换链表中的节点

.1- 题目解析

        以示例 1 为例。我们可以引入一个头节点,并定义四个指针变量来表示不同的节点。

        由此,要实现题目要求的交换,仅需交换 cur 和 next 指向的节点即可,然后将这四个指针整体向后移动,继续完成下次交换,直到 cur 遇到了空节点,说明此时整个链表都完成了交换。

.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* swapPairs(ListNode* head) {if(head==nullptr||head->next==nullptr)return head; //处理边界情况ListNode* newhead=new ListNode(0);newhead->next=head;ListNode* prev=newhead,*cur=newhead->next;ListNode* next=cur->next,*nnext=next->next;while(cur && next){//交换 cur 和 nextcur->next=nnext;next->next=cur;prev->next=next;//继续遍历链表prev=cur;cur=nnext;if(cur)next=cur->next;if(next)nnext=next->next;}cur=newhead->next;delete newhead;return cur;}
};

3)重排链表

重排链表. - 力扣(LeetCode)

.1- 题目解析

        以示例 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:void reorderList(ListNode* head) {if(head==nullptr||head->next==nullptr||head->next->next==nullptr)return;//找到原始链表的中间位置ListNode* fast=head,*slow=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;}//头插法逆序后半部分ListNode* newhead=new ListNode(0);ListNode*cur=slow->next,*next=cur->next;slow->next=nullptr; //断开前后两个链表while(cur){next=cur->next;cur->next=newhead->next;newhead->next=cur;cur=next;            }//合并两个链表ListNode* ret=new ListNode(0);ListNode* prev=ret;ListNode* cur1=head,*cur2=newhead->next;while(cur1){prev->next=cur1;cur1=cur1->next;prev=prev->next;if(cur2){prev->next=cur2;cur2=cur2->next;prev=prev->next;}}delete newhead;delete ret;}
};

4)合并 K 个升序链表

23. 合并 K 个升序链表

.1- 题目解析

        要合并 K 个升序链表,可以先合并两个升序链表,再继续两两合并剩下的链表。我们可以用优先级队列(建小根堆排升序)来优化这个过程,将所有链表的头节点依此入队,即可找到最小的那个节点,只需将其尾插入一个新的头节点,然后将后续的节点入队,重复这个过程,就可以完成 K 个升序链表的合并了。

        另外,先合并两个升序链表,再继续两两合并剩下的链表,也可以用归并的方式来解决。

.2- 代码编写

//法1:优先级队列
/*** 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 {struct cmp{bool operator()(const ListNode* l1,const ListNode* l2){return l1->val > l2->val;}};
public: ListNode* mergeKLists(vector<ListNode*>& lists) {//创建一个小根堆priority_queue<ListNode*,vector<ListNode*>,cmp> heap;//让所有链表的头节点进行小根堆for(auto l: lists) if(l)heap.push(l);//合并链表ListNode* ret=new ListNode(0);ListNode* prev=ret;while(!heap.empty()){auto t=heap.top();//每次取堆顶元素heap.pop();prev->next=t;//链接prev=t;if(t->next) //将后续的节点入堆heap.push(t->next);}prev=ret->next;delete ret;return prev;}
};
//法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* mergeKLists(vector<ListNode*>& lists) {return merge(lists,0,lists.size()-1);}ListNode* merge(vector<ListNode*>&lists,int left,int right){if(left>right)return nullptr;if(left==right)return lists[left];//平分数组int mid=(left+right)>>1;//递归处理左右区间ListNode* l1=merge(lists,left,mid);ListNode* l2=merge(lists,mid+1,right);//合并两个有序链表return mergeTowlist(l1,l2);}ListNode* mergeTowlist(ListNode* l1,ListNode* l2){if(l1==nullptr)return l2;if(l2==nullptr)return l1;ListNode head;ListNode* cur1=l1,*cur2=l2,*prev=&head;head.next=nullptr;while(cur1&&cur2){if(cur1->val<=cur2->val){prev->next=cur1;prev=cur1;cur1=cur1->next;}else{prev->next=cur2;prev=cur2;cur2=cur2->next;}}if(cur1)prev->next=cur1;if(cur2)prev->next=cur2;return head.next;}
};

5)K 个一组翻转链表

25. K 个一组翻转链表

.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* reverseKGroup(ListNode* head, int k) {//1.先求出需要逆序多少组int n=0;ListNode* cur=head;while(cur){cur=cur->next;n++;}n/=k;//2.重复n次,长度为k的链表逆序ListNode* newHead=new ListNode(0);ListNode* prev=newHead;cur=head;for(int i=0;i<n;i++){ListNode* tmp=cur;for(int j=0;j<k;j++){ListNode* next=cur->next;cur->next=prev->next;prev->next=cur;cur=next;}prev=tmp;}prev->next=cur;cur=newHead->next;delete newHead;return cur;}
};

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

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

相关文章

linux kernel 6.x 用户态地址空间探究

最近做个项目需要研究用户态虚拟地址划分情况&#xff0c;找到多个app的共有未使用区间。偶然发现6.1.49和6.8的kernel用户态虚拟地址划分似乎有些不一样。下面使用数据进行分析。 大家都知道linux应用空间的地址划分是&#xff1a; stack高地址开始&#xff0c;向下生长。mm…

换脸动漫转真人:ComfyUI无实物Cosplay

在数字艺术领域&#xff0c;将动漫角色转换为真人形象一直是艺术家的追求。现在&#xff0c;ComfyUI推出了无实物Cosplay功能&#xff0c;让你轻松实现换脸动漫转真人&#xff0c;开启你的二次元冒险之旅&#xff01; ComfyUI无实物Cosplay&#xff1a;换脸动漫转真人&#xf…

Elasticsearch 向量数据库本地部署 及操作方法

elasticsearch是个分布式向量数据库&#xff0c;支持多种查找模式。此外还拥有 Metadata、Filtering、Hybrid Search、Delete、Store Documents、Async等能力。本文仅是记录本地测试途中遇到的问题。 一&#xff0c;环境部署 下载软件 首先去官网&#xff0c;选择适合平台下…

黑龙江等保测评:保障数据安全的最佳选择,助力企业无忧发展!

在数字化时代&#xff0c;数据安全已成为企业发展的重中之重。尤其是在黑龙江&#xff0c;随着信息技术的快速发展&#xff0c;数据泄露和网络攻击的风险日益增加。为了帮助企业提升数据安全防护能力&#xff0c;黑龙江等保测评应运而生&#xff0c;成为保障数据安全的有力工具…

在代码平台怎么拉取对应分支的项目,并且创建属于自己的分支

1.找到对应的代码平台比如gitee,gogs 我这里是gogs 这里有一个网址,把他复制下来 2.打开你想放到的idea路径 输入cmd 输入 这是网上找的项目 git clone http://192.168.150.101:10880/tjxt/tianji.git -b lesson-init 这里的git clone是克隆,这里的-b是分隔符,lesson-ini…

论文120:Giga-SSL: Self-supervised learning for gigapixel images (2023, CVPR, 开源)

文章目录 1 要点2 方法2.1 算法设计2.2 设计选择 1 要点 题目&#xff1a;用于千兆像素图像的自监督学习 (Giga-SSL: Self-Supervised Learning for Gigapixel Images) 代码&#xff1a;https://github.com/trislaz/gigassl 研究目的&#xff1a; 现有的WSI分类方法依赖于有…

【Proteus51单片机仿真】YL-69湿度检测和继电器电机自启动

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于AT89C51单片机&#xff0c;湿度检测模块通过ADC0832数模转换器&#xff0c;将模拟信号转换为数字信号给单片机&#xff0c;然后通过LCD1602显示屏显示出当前的湿度值&#xff0c;并判断当前湿度值是…

CSS 常用元素属性

CSS 属性有很多, 可以参考文档 CSS 参考手册 1. 字体属性 设置字体 多个字体之间使用逗号分隔. (从左到右查找字体, 如果都找不到, 会使用默认字体. )如果字体名有空格, 使用引号包裹.建议使用常见字体, 否则兼容性不好. <style>.one {font-family:"Microsoft Ya…

Machine Learning: A Probabilistic Perspective 机器学习:概率视角 PDF免费分享

下载链接在博客最底部&#xff01;&#xff01; 之前需要参考这本书&#xff0c;但是大多数博客都是收费才能下载本书。 在网上找了好久才找到免费的资源&#xff0c;浪费了不少时间&#xff0c;在此分享以节约大家的时间。 链接: https://pan.baidu.com/s/1erFsMcVR0A_xT4fx…

无人机遂行编队飞行中的纯方位无源定位(2022数模国赛B题)

文章目录 论文项目地址 数模国赛前的练手题&#xff0c;实力不够&#xff0c;参考了好多论文才写出来&#xff0c;个人感觉思路应该没什么大问题&#xff0c;供大家参考 论文 项目地址 github&#xff1a;UAVFormationFlight gitee&#xff1a;UAVFormationFlight 项目包含 完…

指针式仪表识别

源码下载&#xff1a;小宅博客网 效果如下&#xff1a; 工程结构&#xff1a; 说明&#xff1a; 源码是针对下面这种刻度&#xff0c;并且单个指针的仪表的 如果是下面这种&#xff0c;刻度线被连接起来的&#xff0c;目前不支持转换成仪表单位&#xff0c;只能输出指针角度&…

探索自动化的魔法:Python中的pyautogui库

文章目录 探索自动化的魔法&#xff1a;Python中的 pyautogui 库背景&#xff1a;为什么选择pyautogui&#xff1f;pyautogui是什么&#xff1f;如何安装pyautogui&#xff1f;五个简单的库函数使用方法场景应用常见Bug及解决方案总结 探索自动化的魔法&#xff1a;Python中的 …

C++初阶:string类的模拟实现

✨✨小新课堂开课了&#xff0c;欢迎欢迎~✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C&#xff1a;由浅入深篇 小新的主页&#xff1a;编程版小新-CSDN博客 前言&#xff1a; 前面已经对string类进行了…

7系列FPGA HR/HP I/O区别

HR High Range I/O with support for I/O voltage from 1.2V to 3.3V. HP High Performance I/O with support for I/O voltage from 1.2V to 1.8V. UG865&#xff1a;Zynq-7000 All Programmable SoC Packaging and Pinout

【mechine learning-六-supervise learning之线性回归模型】

监督学习之线性回归模型 线性回归模型线性模型回归模型 如何使用线性模型实现智能化预测呢寻找数据训练模型输入、特征、目标、预测值、模型代价函数 线性模型是人工智能监督学习中最广泛的应用&#xff0c;所以有必要先学习一下这个基础模型&#xff0c;做好基石。 线性回归模…

使用 ShuffleNet 模型在 CIFAR-100 数据集上的图像分类

简介 在深度学习领域&#xff0c;图像分类任务是衡量算法性能的重要基准。本文将介绍我们如何使用一种高效的卷积神经网络架构——ShuffleNet&#xff0c;来处理 CIFAR-100 数据集上的图像分类问题。 CIFAR-100 数据集简介 CIFAR-100 数据集是一个广泛使用的图像分类数据集&…

Python爱心射线(完整代码)

目录 系列目录 写在前面​ 完整代码 下载代码 代码分析 写在后面 系列目录 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3

人工智能领域各方向顶级会议和期刊

会议 人工智能基础与综合&#xff1a;AAAI、CICAI (!)、UAI、IJCAI 机器学习&#xff1a;COLT、ICLR、ICML、NeurIPS 模式识别与计算机视觉&#xff1a;ECCV、CVPR、ICCV 语言与语音处理&#xff1a;ACL、EMNLP 知识工程与数据挖掘&#xff1a;SIGKDD、SIGMOD、ICDE、SIGIR、V…

web知识

sql注入的万能密码:1’ or true#如果页面没有什么东西可见&#xff0c;首先可以用diresearch看看有没有什么隐藏的目录&#xff0c;或者检查源代码&#xff0c;如果这些都没成功可以用 dirsearch如果没有找到东西&#xff0c;可能需要调低线程 dirsearch.py -u url -e * --ti…

语音转文字工具全解析

无论是学生群体记录课堂笔记&#xff0c;职场人士整理会议纪要&#xff0c;还是自媒体创作者捕捉灵感火花&#xff0c;录音转文字软件都以其独特的便利性和高效性赢得了广泛的好评。今天&#xff0c;就让我们一起探索那些深受大家喜爱的录音转文字工具吧。 1.365在线转文字 链…