【优选算法】链表

在这里插入图片描述

目录

  • 链表常用的技巧和操作
    • 1、常用技巧
    • 2、常用操作
  • 一、[两数相加](https://leetcode.cn/problems/add-two-numbers/description/)
  • 二、[两两交换链表中的节点](https://leetcode.cn/problems/swap-nodes-in-pairs/description/)
  • 三、[重排链表](https://leetcode.cn/problems/reorder-list/description/)
  • 四、[合并 K 个升序链表](https://leetcode.cn/problems/merge-k-sorted-lists/description/)
  • 五、[K 个一组翻转链表](https://leetcode.cn/problems/reverse-nodes-in-k-group/description/)
  • 结尾

链表常用的技巧和操作

1、常用技巧

  1. 画图

  2. 引入虚拟头结点

    • 便于我们处理边界情况
    • 方便我们对链表进行操作
  3. 不要吝啬空间,大胆定义变量
    相信我们在上学期间学习过数据结构的同学都很熟悉,给你两个节点,使用双向链接将其链接起来,但是只给你一个节点的地址,要求你在两个节点之间插入一个新节点,大家可能都被链接的顺序恶心过,但是只要定义一个变量记录另一个节点的地址,那么我们想怎么链接就怎么链接了。

  4. 快慢双指针

2、常用操作

  1. 创建一个新节点
  2. 头插
  3. 尾插

一、两数相加

题目描述
在这里插入图片描述

思路讲解
本道题只需要模拟两数相加的过程即可,首先定义一个虚拟头结点,这样就不需要对链表进行特殊处理,然后定义两个变量分别记录对应位上两数相加的个位和进位,创建一个节点存储个位上的数字,尾插到虚拟头结点所在的链表中,然后同时将两个原始链表向后同时移动,重复上面的操作,直到两个链表都遍历完后返回以虚拟头结点后面一个节点为头结点的链表即完成本题。

需要注意两数相加时还要加上进位,若是某个链表对应位上没有节点,我们认定这个节点上的数字为0。

编写代码

/*** 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) {int add = 0;ListNode* newhead = new ListNode();ListNode* cur = newhead;while(l1 || l2 || add){int num1 = (l1 != nullptr) ? l1->val : 0;int num2 = (l2 != nullptr) ? l2->val : 0;int sum = num1 + num2 + add;ListNode* newNode = new ListNode(sum % 10);cur->next = newNode;cur = cur->next;add = sum / 10;if(l1 != nullptr)   l1 = l1->next;if(l2 != nullptr)   l2 = l2->next;}return newhead->next;}
};

二、两两交换链表中的节点

题目描述
在这里插入图片描述

思路讲解
本道题我们需要做的就是将链表中每两个节点进行交互即可,我们只需要模拟如何将节点进行交换即可。若链表中只有一个节点时,不需要进行交换,返回即可。

这里我创建一个虚拟头结点用来避免对链表第一次交换进行特殊处理,通过画图我们发现,看似是对两个节点进行交换,实际上却涉及到了四个节点,为了我们方便处理,直接定义四个指针分别指向四个连续的节点,有了这四个指针就可以很方便的将两个节点进行交换了,如下图,我们只需要修改prve、cur和next指向节点中next的指向即可,修改完指向后就需要指针向后移动了,各个指针移动后对应的位置在下图中有明确的标识,有些指针移动后位置比较特殊,需要特殊判断。

在这里插入图片描述

然后就是循环的判断条件了,这里我们将链表分类奇数节点个数和偶数节点个数来看,如图,奇数情况下只要next没有指向节点就结束,偶数情况下cur没有指向节点就结束,综上只要cur或next有一个没有指向节点就结束循环。最后返回以虚拟头结点后面一个节点为头结点的链表即完成本题。
在这里插入图片描述

编写代码

/*** 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();ListNode* prev = newhead ,*cur = head ;ListNode* next = head->next , *nnext = next->next;while(cur != nullptr && next != nullptr){prev->next = next;next->next = cur;cur->next = nnext;prev = cur;cur = nnext;if(cur)next = cur->next;if(next)nnext = next->next;}return newhead->next;}
};

三、重排链表

题目描述
在这里插入图片描述

思路讲解

本道题是让我们将链表重新排序,并且不能只修改节点的值,而是要进行节点之间的切换,我们看了题目的示例,可以得出重排链表,实际上是重复拿出原链表中的头节点和尾节点,并将尾节点链接到头节点的后面,然后按照拿出来的顺序进行链接,即可完成对链表的重排。

本题还有一个更简单的思路,就是将这个链表从中间分开变为两个链表,使前面链表的节点个数比后面的链接节点个数多一个或是相等,然后将后面这个链表逆转,最后通过两个链表的合并即可完成链表的重排。

编写代码

/*** 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->next == nullptr)return;ListNode* slow = head , *fast = head -> next;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}// 从中间截断为两段链表ListNode* newhead1 = new ListNode();ListNode* cur = slow -> next;slow->next = nullptr;ListNode* next = cur->next;// 逆置后半段链表cur->next = nullptr;while(cur){cur->next = newhead1->next;newhead1 -> next = cur;cur = next;if(next)next = next -> next;}ListNode* cur1 = head ,*cur2 = newhead1->next;ListNode* next1 = head->next ,*next2 = cur2->next;ListNode* newhead2 = new ListNode();cur = newhead2;while(cur2){// 依次插入两个链表cur -> next = cur1;cur1 = next1;if(next1)next1 = next1->next;cur = cur -> next;cur -> next = cur2;cur2 = next2;if(next2)next2 = next2->next;cur = cur -> next;}// 第一段链表一定与第二段链表等长或更长if(cur1)cur->next = cur1;head = newhead2;}
};

四、合并 K 个升序链表

题目描述
在这里插入图片描述

思路讲解
本道题是想让我们将k个升序链表,按照节点的大小合并为1个升序链表,这里我们一定能想到的就是暴力解法,每次遍历所以链表的头节点,找到最小的节点并取出,再将这个节点链入到新链表中,重复这样的操作,直到k个链表中没有任何节点位置,最后返回新链表即可完成本道题,这样完成本道题的时间复杂度为O(nk2^22)。

这里可以使用优先级队列进行优化,我们创建一个小堆,将所有链表的头节点放入小堆中,小堆根据节点的大小将最小的节点移动到堆顶,这样我们就可以通过找到堆顶元素就可以找到k个链表中头节点中最小的节点了,将该节点从堆中和它所对应的链表中取出,并将它所对应链表中的新头节点放入到堆中,若没有节点则不需加入,小堆则会按照它的特性将堆中的节点重新调整,然后将取出来的节点链接到新的链表中,重复这样的操作直到堆中没有任何节点为止,最后将新链表返回即可完成合并 K 个升序链表。

编写代码

/*** 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) {int count = lists.size(); // 链表的个数ListNode* newhead = new ListNode();ListNode* last = newhead;// 记录链表中有节点的链表个数int ListCount = 0;while(1){int MinPos = 0;int min = 10001;for(int i = 0 ; i < count; i++){ListNode* cur = lists[i];if(cur){   ListCount++;if(min > cur->val){min = cur->val;MinPos = i;}}}// 当链表所有链表都没有节点时跳出循环if(ListCount == 0)break;last->next = lists[MinPos];// 插入到新的链表中last = last -> next;if(lists[MinPos])lists[MinPos] = lists[MinPos]->next;MinPos = 0 , ListCount = 0;}return newhead->next;}
};

五、K 个一组翻转链表

题目描述
在这里插入图片描述

思路讲解
本道题想让我们将链表中每k个节点进行翻转,若剩下的节点小于k个则保持愿意。

这里可以使用模拟的思路解决本题,我们先遍历整个链表,得到链表中节点的个数为num,有每k个节点需要翻转一次,通过num/k得到有count组子链表需要翻转。循环count次,每次记录该组子链表的前一个节点和后一个节点,将本组k个节点进行逆序,再链接回原链表中,这里可以使用头插法的方式将链表进行逆序,最后返回链表的头结点即可。

编写代码

/*** 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) {int numNode = 0;  // 节点个数ListNode* cur = head;while(cur){numNode++;cur = cur->next;}int opCount = numNode / k;  // 记录需要翻转的次数ListNode* newhead = new ListNode();   // 创建哨兵位头结点newhead->next = head;ListNode* prev = newhead; // 标记每k个节点的前一个节点,方便链接cur = head;ListNode* connect = cur; // 旋转k个节点后的最后一个节点,方便链接ListNode* next = cur->next; while(opCount--){connect = cur;for(int i = 1 ; i <= k ; i++){cur->next = prev->next;prev->next = cur;cur = next;if(next)next = next->next;}// 记录前一段的尾prev = connect;}prev->next = cur;return newhead->next;}
};

结尾

如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。
希望大家以后也能和我一起进步!!🌹🌹
如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹

在这里插入图片描述

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

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

相关文章

制造业新突破:AR 培训系统助力复杂操作轻松上手​

在制造业&#xff0c;生产设备复杂、操作流程繁琐&#xff0c;新员工掌握操作技能不易。比如汽车制造企业的发动机装配环节&#xff0c;涉及众多精密零部件安装&#xff0c;对安装顺序、位置精度要求严格&#xff0c;一点小失误都可能影响发动机性能甚至引发质量问题。过去新员…

《计算机网络》实验报告八 加密、数字签名与证书

目 录 1、实验目的 2、实验环境 3、实验内容 3.1 对称加密 3.2 散列函数 3.3 非对称加密 3.4 数字签名 3.5 证书 4、实验结果与分析 4.1 对称加密 4.2 散列函数 4.3 非对称加密 4.4 数字签名 4.5 证书 5、实验小结 5.1 问题与解决办法&#xff1a; 5.2 心得体…

MySQL(157)如何分析和优化存储过程?

分析和优化存储过程是数据库性能优化的重要环节。通过对存储过程进行分析和优化&#xff0c;可以提高数据库操作的执行效率&#xff0c;减少资源消耗&#xff0c;改善系统整体性能。以下是详细的步骤和代码示例&#xff0c;介绍如何分析和优化 MySQL 存储过程。 一、分析存储过…

基于深度学习的胸部 X 光图像肺炎分类系统(一)

本文先重点介绍了过采样的原理是实现。 由于医学数据相对缺乏&#xff0c;过采样是解决数据问题的方法之一。 后续写一篇搭建神经网络的说明 目录 概述 导入必要的库 数据加载和预处理函数 处理样本不均衡函数 构建改进的 CNN 模型函数 主函数 数据生成器generator&…

【PGCCC】在 Postgres 中构建复制安全的 LSM 树

在原生 Postgres 实现中&#xff0c;全文搜索由B 树或GIN&#xff08;广义倒排索引&#xff09;结构支持。这些索引针对相对快速的查找进行了优化&#xff0c;但受限于 B 树的写入吞吐量。 当我们构建pg_searchPostgres 搜索和分析扩展时&#xff0c;我们的优先级有所不同。为了…

架构如钟摆:在变与不变之间优雅平衡

在当今数字转型浪潮中&#xff0c;企业在“快速创新”与“长期稳定”之间反复拉扯。是否应该重建所有架构以适应AI&#xff1f;又是否该死守传统系统确保安全与合规&#xff1f;在The Open Group阿姆斯特丹峰会上&#xff0c;凯捷全球 CTO Ron Tolido 借用了一个极具画面感的比…

LLM中的位置嵌入矩阵(Position Embedding Matrix)是什么

LLM中的位置嵌入矩阵(Position Embedding Matrix)是什么 在大语言模型(LLM)中,位置嵌入矩阵(Position Embedding Matrix) 是用来表示输入序列中每个词的位置信息的矩阵。它的核心作用是:让模型能够区分“相同词在不同位置的语义差异”(比如“猫喜欢鱼”中的“猫”和“…

国产DevOps平台Gitee:如何重塑中国企业研发效能新格局

国产DevOps平台Gitee&#xff1a;如何重塑中国企业研发效能新格局 在全球数字化转型浪潮中&#xff0c;软件研发效率已成为企业竞争力的核心指标。作为中国最大的代码托管平台&#xff0c;Gitee正通过其全栈式DevOps解决方案&#xff0c;助力中国企业突破研发效能瓶颈&#xff…

告别混乱!【Java Web】项目分层架构全指南:核心三层 + 关键辅助包详解

目录 1.前言 2.正文 2.1为什么要分层 2.2核心三层详解 2.2.1Controller层&#xff08;表现层/API层&#xff09; 2.2.2Service层&#xff08;业务逻辑层&#xff09; 2.2.3DAO层&#xff08;持久层&#xff09; 2.3. 核心关系与数据流转&#xff1a;分层架构的交互逻辑…

解决Docker Compose报错

解决Docker Compose报错&#xff1a;exec ./entrypoint.sh: no such file or directory在使用Docker Compose部署应用时&#xff0c;你是否遇到过exec ./entrypoint.sh: no such file or directory这个令人头疼的错误&#xff1f;本文将深入分析错误原因并提供多种解决方案&…

【element plus】el-select,allow-create不需要点回车键

<el-selectv-model"row.expertName"filterableremoteallow-createdefault-first-optionreserve-keywordplaceholder"请输入姓名":remote-method"remoteMethod":loading"loadingName"change"(val) > handleNameChange(row, …

RK3588 HDMI-RX 驱动、RGA 加速与 OpenCV GStreamer 支持完整指南

一、环境检测与前置依赖 确认内核与 HDMI-RX 节点&#xff1a; uname -a # 输出&#xff1a;6.1.0-1025-rockchip ...dmesg | grep -i hdmirx # 应能看到 hdmirx-controller 节点&#xff1a; # fdee0000.hdmirx-controller driver probe ok!如果仅出现&#xff1a; rockchi…

AS32A601芯片QSPI 调试技术解析与与实战经验分享

一、概述&#xff08;一&#xff09;QSPI 简介QSPI&#xff08;Quad Serial Peripheral Interface&#xff09;是一种高速串行通信接口&#xff0c;在标准 SPI&#xff08;Serial Peripheral Interface&#xff09;的基础上扩展至 4 条数据线&#xff08;Quad Mode&#xff09;…

TDengine 转化函数 TO_TIMESTAMP 用户手册

TDengine TO_TIMESTAMP 函数用户使用手册 函数概述 TO_TIMESTAMP 是 TDengine 中的标量函数&#xff0c;用于将字符串按照指定格式转换为时间戳。该函数在数据导入、时间格式转换、以及处理各种时间字符串格式时非常有用。 语法 TO_TIMESTAMP(ts_str_literal, format_str_liter…

关于我司即将对商业间谍行为进行法律诉讼的通知

最后警告我司所属社交媒体中所有友商间谍&#xff1a;请于2025年7月26日上午十点前&#xff0c;自行删除我方好友&#xff0c;并停止通过欺诈行为&#xff08;包括但不限于冒充客户等&#xff09;盗取我司商业秘密的行为。十点后&#xff0c;我司将开始进行逐一排查&#xff0c…

【打怪升级 - 03】YOLO11/YOLO12/YOLOv10/YOLOv8 完全指南:从理论到代码实战,新手入门必看教程

引言&#xff1a;为什么选择 YOLO&#xff1f; 在目标检测领域&#xff0c;YOLO&#xff08;You Only Look Once&#xff09;系列模型一直以其高效性和准确性备受关注。作为新版本&#xff0c;YOLO系列的新版本总能在前辈的基础上进行了多项改进&#xff0c;包括更高的检测精度…

JMeter每次压测前清除全部以确保异常率准确(以黑马点评为例、详细图解)

目录 一、前言 二、未清除全部会出现的情况(以乐观锁解决超卖问题为例) 三、清除全部就能得到准确的结果 一、前言 在学习黑马点评之前我并没有接触过JMeter这个压测软件&#xff0c;然后在黑马点评视频中老师也是直接拿起JMeter就开始使用&#xff0c;所以我一直在不断搜索…

关于新学C++编程Visual Studio 2022开始,使用Cmake工具构建Opencv和SDK在VS里编译项目开发简介笔记

1. C 项目build文件夹 2. VS解决方案管理器Solution——.sln文件 3. CMake 自动化构建工具 4. SDK软件开发工具包作为初学者&#xff0c;从工程项目开始接触完整一套流程工具和编译&#xff0c;有助于快速上手。 一、C 项目build文件夹在 VS2022 中打开 C 项目后&#xff0c;在…

测试ppyoloe的小样本few-shot能力,10张图片精度达到69.8%

近期公司有个项目&#xff0c;需要解决长尾样本的问题&#xff0c;所以测试了一下paddlepaddle小样本的能力。 环境&#xff1a;&#xff1a;T4 、ubuntu 、cuda-11.6 、py3.9、 paddlepaddle-gpu2.6.0、pip install opencv-python4.5.5.64 -i https://pypi.tuna.tsinghua.…

结构化布线系统详解

1. 结构化布线系统概述 结构化布线系统(Structured Cabling System, SCS)是一种标准化、模块化的建筑物或建筑群内信息传输基础设施&#xff0c;它为语音、数据、图像等多媒体业务提供了统一的物理传输介质。与传统的点对点布线方式不同&#xff0c;结构化布线采用层次化、标准…