链表题目之指定区间处理

前言

链表中有一些题目是需要知道并且记住对应的技巧的,有一些题目就是基本的链表技巧+手动模拟推演注意细节等。
对于需要知道并且记住对应技巧的题目会有专门的一栏进行讲解,此类题目主要有:相交链表、环形链表、回文链表等,这些必须要记住对应的破题的题眼。
本文主要是讲指定区间的链表,这类题目有一定的共性,而且常考变形题目也较多。

理论

此类题目大概是给你一个链表,让你按照某个条件,找到一个区间的开始位置,之后对这个区间一直处理直到这个区间的结束位置,当然一个链表中可能有多处这样的区间。这里涉及到的技巧在基本方法篇已经有讲,实际上就是构造、处理部分的各种组合,这里按照做题时的先后顺序归纳一下。

  1. 虚拟头:如果第一个节点会是区间开始位置,要用虚拟头
  2. 找区间开始位置,以及不符合条件时继续
  3. 小区间for循环处理:找到区间开始位置后,要用for循环小区间内一次性处理,直到这个区间结束
  4. 小区间内具体处理:重新做人法,即别用p了,直接用一个新的变量,进行赋值,避免乱,同时也能保留关键上下文。具体方案:删除(前任删除法)、反转(头插)
  5. 小区间处理完之后,要收摊子,要把处理的这部分接回去

基本框架流程如下

  1. 虚拟头
func solve(head *ListNode) *ListNode {dummyHead := &ListNode{Next:head}p := dummyHeadreturn dummyHead.Next
}
  1. 找区间入口
  2. 找到区间出口
func solve(head *ListNode) *ListNode {dummyHead := &ListNode{Next:head}p := dummyHeadfor p.Next != nil {if xx {}p = p.Next}return dummyHead.Next
}
  1. 小区间for循环处理
func solve(head *ListNode) *ListNode {dummyHead := &ListNode{Next:head}p := dummyHeadfor p.Next != nil {if xx {// 找到区间入口了tmpP := p.Next // 重新做人for xx { // for 循环直到区间出口}}p = p.Next // 不符合条件 继续下一个}return dummyHead.Next
}
  1. 小区间处理完之后,要收摊子,要把处理的这部分接回去,注意之前的p以及p.Next指向的值,很关键
  2. 手动推演,即下一轮循环p的位置
func solve(head *ListNode) *ListNode {// 1.把框架复制进来,看一下 是否能行dummyHead := &ListNode{Next:head}p := dummyHeadfor p.Next != nil {if xx { // 2. 根据题目要求写一下这个的入口条件和下面的出口条件// 找到区间入口了tmpP := p.Next // 重新做人// 3. 区间出口for xx { // for 循环直到区间出口 // 4.具体处理逻辑}// 5.接回去 具体根据题目分析,注意之前的p以及p.Next指向的值,很关键// 6.即下一轮循环p的位置:手动推演一下}p = p.Next // 不符合条件 继续下一个}return dummyHead.Next
}

实战

接下来会使用几个题目,根据上面的套路、模版进行编码

指定区间反转链表(92)

题目:92. 反转链表 II
代码中的1、2、3即为思考编码时候的步骤

/*** Definition for singly-linked list.* type ListNode struct {*     Val int*     Next *ListNode* }*/
func reverseBetween(head *ListNode, left int, right int) *ListNode {// 1.把框架复制进来,看一下 是否能行,这里是可行的dummyHead := &ListNode{Next:head}p := dummyHeadindex := 0for p.Next != nil {index++if index==left { // 2. 根据题目要求写一下这个的入口条件和下面的出口条件,看来得用Index记录一下// 找到区间入口了// 4. 是想让我们反转,那就头插,基本套路写上var newHead *ListNodetmpP := p.Next // 重新做人for index<=right { // for 循环直到区间出口index++ // 3. 区间出口,这里肯定要++ ,具体是<=还是=可以用推演确定cur := tmpPtmpP = tmpP.Nextcur.Next = newHeadnewHead = cur}// 接回去 具体根据题目分析,注意之前的p以及p.Next指向的值,很关键// 5.手动推演以及p的信息,可以知道当前p是1,p.Next是2,newHead是4,tmpP是5,对应接上即可// 要注意顺序p.Next.Next = tmpPp.Next = newHead// 6.这里其实可以break了break}p = p.Next // 不符合条件 继续下一个}return dummyHead.Next
}

删除排序链表中的重复元素2(82)

题目:82. 删除排序链表中的重复元素 II

func deleteDuplicates(head *ListNode) *ListNode {// 删除所有重复的元素,使每个元素只出现一次// 1.把框架复制进来,看一下 是否能行dummyHead := &ListNode{Next:head}p := dummyHeadfor p.Next != nil {if p.Next.Next != nil && p.Next.Val == p.Next.Next.Val { // 2. 根据题目要求写一下这个的入口条件和下面的出口条件// 2. 这里就是下一个节点和下下个节点的值一样,用到了NN,额外判断nil// 找到区间入口了tmpP := p.Next // 重新做人// 3. 区间出口 这里其实和if条件里的是一样的条件for tmpP.Next != nil && tmpP.Val == tmpP.Next.Val {// 4.具体处理逻辑,得手动推演了,// 4.1 0 1 1 2,当前tmpP是1,最开始是符合,然后tmpP到第二个1,然后就不符合了,退出区间tmpP = tmpP.Next // 4.2 相等就往后走}// 此时tmpP指向了第二个1,题目要求每个保留一次,那就只保留最后一个,// 5.接回去 具体根据题目分析,注意之前的p以及p.Next指向的值,很关键// 5.1 此时p是0,tmpP是第二个1,中间的不要了(算是删除了)p.Next = tmpP// 6.这里需要考虑要不要break或者Continue,手动推演一下}p = p.Next // 不符合条件 继续下一个}return dummyHead.Next
}

删除排序链表中的重复元素(83)

题目:83. 删除排序链表中的重复元素

/*** Definition for singly-linked list.* type ListNode struct {*     Val int*     Next *ListNode* }*/
func deleteDuplicates(head *ListNode) *ListNode {// 删除原始链表中所有重复数字的节点,只留下不同的数字// 1.把框架复制进来,看一下 是否能行dummyHead := &ListNode{Next:head}p := dummyHeadfor p.Next != nil {if p.Next.Next != nil && p.Next.Val == p.Next.Next.Val { // 2. 根据题目要求写一下这个的入口条件和下面的出口条件// 2.1 这里的入口就是有重复的// 找到区间入口了tmpP := p.Next // 重新做人// 3. 区间出口,这里就是按入口的条件一直执行到不符合要求,即为出口for tmpP.Next != nil && tmpP.Val == tmpP.Next.Val { // for 循环直到区间出口 // 4.具体处理逻辑,不断往后走,直到找到最后一个重复的tmpP = tmpP.Next}// 5.接回去 具体根据题目分析,注意之前的p以及p.Next指向的值,很关键.手动推演,注意这里是一个不留// 以 0 [1,1,1,2,3] 为例,走到这里的时候 p指向0,p.Next指向第一个1,tmpP指向的是最后一个1,最终结论是 一个不留p.Next = tmpP.Next// 6.这里需要考虑要不要break或者Continue,即p要不要移动,这里不能移动continue}p = p.Next // 不符合条件 继续下一个}return dummyHead.Next
}

两两交换链表中的节点(24)

题目:24. 两两交换链表中的节点
下面这个其实写废了,想写一个支持N=任意数的,但是忽略了本题的隐藏条件,不足N个不进行调整
以及另一个重要条件,N=任意数实际上对应K个一组翻转链表这个题目,难度是Hard。

func swapPairs(head *ListNode) *ListNode {// 1.把框架复制进来,看一下 是否能行dummyHead := &ListNode{Next:head}p := dummyHeadindex:=0count := 2for p.Next != nil {index++if index == 1 { // 2. 根据题目要求写一下这个的入口条件和下面的出口条件// 2.1 这里得用一个Index记录,index可以每次置0,也可以每次求余数,这里置0// 2.2 这里判断index == 1实际上是有点废话。可以结合下面的for循环进行优化。其实还好// 找到区间入口了tmpP := p.Next // 重新做人var newHead *ListNode// 3. 区间出口,这里同时要把Index增加的代码写上,避免忘啦for index <= count && tmpP.Next != nil { // for 循环直到区间出口 // !!! 不足的情况没考虑啊,比如1个,或者3个// !!! 本题 隐藏条件,不足x个不进行调整index++// 4.具体处理逻辑,这不就是链表逆序?!cur := tmpPtmpP = tmpP.Nextcur.Next = newHeadnewHead = cur}// 5.接回去 具体根据题目分析,注意之前的p以及p.Next指向的值,很关键// 5. 对于0 - 1 2 3 4 --> 0 - 2 1 3 4,此时 p指向0,p.Next是1,tmpP是3,p.Next.Next = tmpPp.Next = newHead// 6.这里需要考虑要不要break或者Continue,手动推演一下,即能不能执行p = p.Next// 6.手动推演,避免空想。 0 - 2 1 3 4 此时p是0,需要让P=1p = p.Next.Nextindex=0continue}// 其实不需要这个了,写了也永远走不到 p = p.Next // 不符合条件 继续下一个}return dummyHead.Next
}

正确解法如下,实际上可以进一步化简,最外层的for其实可以和里面的if判断条件只保留一个。
手动推演部分这里给出画图示例,这个也是本题的复杂点,弄不好容易乱。同时需要注意 如果tmp1 := p.Next
这时候修改了tmp1.Next的值,实际上就是修改了p.Next的值,不要掩耳盗铃以为没有修改。
在这里插入图片描述

func swapPairs(head *ListNode) *ListNode {// 1.把框架复制进来,看一下 是否能行dummyHead := &ListNode{Next: head}p := dummyHeadfor p.Next != nil {if p.Next != nil && p.Next.Next != nil { // 2. 根据题目要求写一下这个的入口条件和下面的出口条件// 2.仅就本题而言,只需要判断 p.Next!=nil && p.Next.Next != nil 即可,之后要做的就是交换这两个// 找到区间入口了// 3.两个节点,一把处理了就行,不需要判断出口,// 4.交换这俩,手动推演一下 0 - 1 2 3--> 0 2 1 3,显然需要记录2,在纸上写一下// 5.这里交换的同时也接上去了tmp := p.Next.Nextp.Next.Next = tmp.Nexttmp.Next = p.Nextp.Next = tmp// 6.看一下下一轮循环p的位置,p = p.Next.Next// // 3. 区间出口// for xx { // for 循环直到区间出口//     // 4.具体处理逻辑// }// 5.接回去 具体根据题目分析,注意之前的p以及p.Next指向的值,很关键// 6.即下一轮循环p的位置:手动推演一下} else {break // 没有需要操作的了,退出}// p = p.Next // 不符合条件 继续下一个,不需要了}return dummyHead.Next
}

K个一组翻转链表

题目:25. K 个一组翻转链表
这个是Hard类型的题目,会单独写一篇文章,详细介绍思考过程和编码过程。

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

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

相关文章

LeetCode | 27.移除元素

这道题的思路和26题一模一样&#xff0c;由于要在元素组中修改&#xff0c;我们可以设置一个index表示目前要修改原数组的第几位&#xff0c;由于遍历&#xff0c;访问原数组永远会在我们修改数组之前&#xff0c;所以不用担心数据丢失的问题&#xff0c;一次遍历数组&#xff…

18. 四数之和 - 力扣

1. 题目 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元组元素一一对应&#xff0c;则认为两个四元组重复&#xff09;&#xff1a; 0 …

LVS+Keepalived NGINX+Keepalived 高可用群集实战部署

Keepalived及其工作原理 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案&#xff0c;可以解决静态路由出现的单点故障问题。 VRRP协议&#xff08;虚拟路由冗余协议&#xff09; 是针对路由器的一种备份解决方案由多台路由器组成一个热备组&#xff0c;通过共用的…

五、LVS原理

目录 5.1 LVS 相关原理 5.1.1 LVS集群的体系结构以及特点 5.1.1.1 LVS简介 5.1.1.2 LVS体系结构 5.1.1.3 LVS相关术语 5.1.1.4 LVS工作模式 5.1.1.5 LVS调度算法 5.1.2 LVS-DR集群介绍 5.1.2.1 LVS-DR模式工作原理 5.1.2.2 LVS-DR模式应用特点 5.1.2.3 LVS-DR模式ARP抑制 5.1…

VCS基本仿真

这里记录三种仿真方式&#xff1a; 第一种是将verilog文件一个一个敲在终端上进行仿真&#xff1b; 第二种是将多个verilog文件的文件路径整理在一个文件中&#xff0c;然后进行仿真&#xff1b; 第三种是利用makefile文件进行仿真&#xff1b; 以8位加法器为例&#xff1a; …

一二三应用开发平台应用开发示例(2)——创建应用、模块、实体及配置模型

创建应用 文档管理系统对于开发平台是一个业务应用。 业务应用是通过平台内置的数据字典来维护的&#xff0c;因此访问系统管理模块下的数据字典管理功能&#xff0c;在实体配置分组下找到“应用编码”&#xff0c;点击行记录上的“字典项”。 在打开的新窗口中&#xff0c;在…

超详解——Python 元组详解——小白篇

目录 1. 元组简介 创建元组 2. 元组常用操作 访问元组元素 切片操作 合并和重复 成员操作符 内置函数 解包元组 元组方法 3. 默认集合类型 作为字典的键 作为函数参数 作为函数的返回值 存储多种类型的元素 4.元组的优缺点 优点 缺点 5.元组的使用场景 数据…

如何降低pcdn的延迟?

要降低P2P CDN的延迟&#xff0c;可以采取以下操作&#xff1a; 一&#xff0e;优化网络连接&#xff1a; 1、使用有线网络连接替代无线连接&#xff0c;因为有线连接通常提供更稳定的数据传输。 2、升级家庭或企业路由器&#xff0c;选择性能更好的路由器以提高网络传输速度…

6月11号作业

思维导图 #include <iostream> using namespace std; class Animal { private:string name; public:Animal(){}Animal(string name):name(name){//cout << "Animal&#xff1b;有参" << endl;}virtual void perform(){cout << "讲解员的…

【FineReport】帆软调用服务器的kettle作业

1、编写自定义函数并编译 package com.fr.function;import ch.ethz.ssh2.ChannelCondition; import ch.ethz.ssh2.Connection; import ch.ethz.ssh2.Session; import ch.ethz.ssh2.StreamGobbler; import com.fr.script.AbstractFunction;import java.io.BufferedReader; impo…

【web APIs】快速上手Day02

文章目录 Web APIs - 第2天事件事件监听案例一 :京东点击关闭顶部广告案例二&#xff1a;随机点名案例拓展知识-事件监听版本 双击事件 事件类型鼠标事件综合案例-轮播图完整版 焦点事件综合案例-小米搜索框案例 键盘事件文本事件 事件对象综合案例-按下回车发布评论 环境对象回…

算法day27

第一题 515. 在每个树行中找最大值 首先是遍历每层的节点&#xff0c;将每一层最大值的节点的值保留下来&#xff0c;最后将所有层的最大值的表返回&#xff1b;具体的遍历每层节点的过程如上一篇故事&#xff1b; 综上所述&#xff0c;代码如下&#xff1a; /*** Definition …

数据结构与算法题目集(中文) 6-3 求链表的表长

该代码使用循环遍历链表来计算链表的长度。代码首先定义了一个整数变量i用于计数&#xff0c;并初始化为0。然后进入一个while循环&#xff0c;条件为链表L非空。在循环中&#xff0c;通过L L->Next来遍历链表中的每一个节点&#xff0c;并将计数变量i递增。最终返回计数变…

2024海南省大数据教师培训-Hadoop集群部署

前言 本文将详细介绍Hadoop分布式计算框架的来源&#xff0c;架构和应用场景&#xff0c;并附上最详细的集群搭建教程&#xff0c;能更好的帮助各位老师和同学们迅速了解和部署Hadoop框架来进行生产力和学习方面的应用。 一、Hadoop介绍 Hadoop是一个开源的分布式计算框架&…

文献解读-农业系列-第七期|《高粱驯化的基因组足迹和多种最终用途的育种选择》

关键词&#xff1a;高粱基因分析&#xff1b;基因组变异检测&#xff1b;全基因组重测序&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;Genomic footprints of sorghum domestication and breeding selection for multiple end uses标题&#xff08;中文…

【Linux系统化学习】传输层——TCP协议

目录 预备知识 全双工协议 协议缓冲区 TCP协议 TCP协议格式 六个标志位 两个问题 确认应答机制 流量控制 超时重传机制 连接管理机制 CLOSE_WAIT状态 TIME_WAIT状态 滑动窗口 拥塞控制 延迟应答 捎带应答 粘包问题 TCP的异常情况 TCP小结 TCP/UDP协议对比…

MAC认证

简介 MAC认证是一种基于接口和MAC地址对用户的网络访问权限进行控制的认证方法&#xff0c;它不需要用户安装任何客户端软件。设备在启动了MAC认证的接口上首次检测到用户的MAC地址以后&#xff0c;即启动对该用户的认证操作。认证过程中&#xff0c;不需要用户手动输入用户名…

成都跃享未来教育抖音小店深度解析靠谱与否

在如今网络购物日益繁荣的时代&#xff0c;抖音小店以其独特的平台优势和庞大的用户基础&#xff0c;吸引了越来越多的商家入驻。成都跃享未来教育咨询有限公司便是其中之一&#xff0c;它的抖音小店究竟靠不靠谱呢&#xff1f;今天&#xff0c;我们就来一起揭开这个谜底。 首…

刷题训练之分治归并

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握分治归并算法。 > 毒鸡汤&#xff1a;学习&#xff0c;学习&#xff0c;再学习 ! 学&#xff0c;然后知不足。 > 专栏选自&#xff1a;刷…

神经气体生长算法【GNG】

当德国计算神经学家 Bernd Fritzke 在其 1995 年的开创性论文中提出后来被称为神经气体生长&#xff08;GNG&#xff09;的算法时&#xff0c;机器学习还是一个相对较新的领域&#xff0c;并且受到实际神经科学的极大启发。 当时&#xff0c;神经科学正处于一个突破性的时代—…