数据结构(Java版)第八期:LinkedList与链表(三)

专栏:数据结构(Java版)
个人主页:手握风云
目录
一、链表中的经典面试题
1.1. 链表分割
1.2. 链表的回文结构
1.3. 相交链表
1.4. 环形链表
一、链表中的经典面试题
1.1. 链表分割

题目中要求不能改变原来的数据顺序,也就是如上图所示。我们先定义一个cur引用去遍历这个链表,用每个结点的val值与x进行比较,然后利用尾插的方法把结点插入进两个链表中。我们先定义bs、be、as、ae四个引用来表示两个链表的头尾,在尾插的时候需要注意,利用ae.next = node;ae = node,记录下尾结点,保证ae永远指向最后一个结点,同时be.next=as,连接上两个链表。
class ListNode{int val;ListNode next = null;public ListNode(int val) {this.val = val;}
}public class Partition {public ListNode partition(ListNode pHead, int x){ListNode bs = null;ListNode be = null;ListNode as = null;ListNode ae = null;ListNode cur = pHead;while(cur != null){if(cur.val < x){}else{}}}
}
代码的大体框架已经写好,这时我们需要考虑一下当第一段插入第一个节点时,第一个节点既是头又是尾。这时有需要分两种情况,第一次插入与下一次插入,来移动be引用。
while(cur != null){if(cur.val < x){//第一次插入if(bs == null){be = bs = cur;}else {be.next = cur;be = cur;}}else{//第一次插入if(as == null){ae = as = cur;}else {ae.next = cur;ae = cur;}}cur = cur.next;
这时的代码还存在一种我们没有想到的情况,如果给定的测试用例都大于x的值呢。这是我们就需要返回as。我们还需要分情况。
if(bs == null){return as;}
如果这是我们放到OJ进行测试,发现报出异常。

这个异常的原因比较隐蔽。因为bs为空,尾节点ae会返回bs,如果ae之前的地址指向之前的某个节点,就会造成链表的死循环,此时我们要将排列之后的链表最后一个节点手动置为null。
完整代码:
class ListNode{int val;ListNode next = null;public ListNode(int val) {this.val = val;}
}public class Partition {public ListNode partition(ListNode pHead, int x){ListNode bs = null;ListNode be = null;ListNode as = null;ListNode ae = null;ListNode cur = pHead;while(cur != null){if(cur.val < x){//第一次插入if(bs == null){be = bs = cur;}else {be.next = cur;be = cur;}}else{//第一次插入if(as == null){ae = as = cur;}else {ae.next = cur;ae = cur;}}cur = cur.next;}if(bs == null){return as;}be.next = as;//连接上两个链表if(as != null){ae.next = null;}return bs;}
}
1.2. 链表的回文结构
第一种思路,我们可以使用双引用算法,一个left引用从左开始向右移动,另一个right引用从右开始向左移动。但由于这个链表是单链表,只能从一个方向遍历。
第二种思路,把链表里的val值取出,存进一个数组中,但题目要求空间复杂度为 。
第三种思路,翻转一半的链表。过程分为三步,第一步,找到链表的中间部分;第二步,将链表的一半进行翻转。我们在上一期中,已经实现了翻转链表和寻找链表的中间节点。

while(cur != null){curN = cur.next;cur.next = slow;slow = cur;cur = curN;
}
利用上面的代码我们就可以来翻转链表,第三步,head从前往后,slow从后往前,比较head.val是否与slow.val相等,直到slow引用与头节点相遇为止。这里我们讨论的是奇数个节点的链表,如果是有偶数个节点的链表,那么fast为空。
当链表的节点为偶数时,我们不能按照之前的做法,当head.next = slow时,直接返回true。

完整代码:
import java.util.Scanner;class ListNode{int val;ListNode next;public ListNode(int val) {this.val = val;}
}public class PalindromeList {public boolean chkPalindrome(ListNode A){//1、找到链表的中间节点ListNode fast = A;ListNode slow = A;while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;}//2、反转链表ListNode cur = slow.next;while(cur != null){ListNode curN = cur.next;cur.next = slow;slow = cur;cur = curN;}//3、引用A与slow同时移动while(A != slow){if(A.val != slow.val){return false;}//判断偶数个节点情况if(A.next == slow){return true;}A = A.next;slow = slow.next;}return true;}
}
1.3. 相交链表
对于链表相交的问题,我们首先要考虑明白,到底是X形相交,还是Y形相交?


如上图所示,很明显两个链表相交之后呈Y形。要解决问题,我们同样利用双引用的算法。第一步,先求出两个链表的长度len1、len2;第二步求出两个链表的长度差len=len1-len2;第三步,让长的链表先走len步;第四步,headA与headA同时走,相遇之后就是公共交节点。
这个题的思路其实很简单,但是其中也有一些比较麻烦的步骤。在第二步中,如果说len1<len2,那么len<0。第三步中,我们又怎么知道哪个链表更长?
class ListNode{int val;ListNode next;ListNode(int x){val = x;next = null;}
}public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB){ListNode pl = headA;//先假设链表A是长的ListNode ps = headB;//求两个链表的长度int len1 = 0,len2 = 0;while(pl != null){len1++;pl = pl.next;}while(ps != null){len2++;ps = ps.next;}pl = headA;ps = headB;//求链表的长度差int len = len1 - len2;if(len < 0){pl = headB;ps = headA;len = len2-len1;}//让pl先走len步while(len != 0){pl = pl.next;len--;}//pl与ps同时走,知道相遇。while(pl != ps){pl = pl.next;ps = ps.next;}//如果没有公共节点,直接返回nullif(pl == null){return null;}return pl;}
}
1.4. 环形链表
快慢引用,即慢引用⼀次⾛⼀步,快引用⼀次⾛两步,两个引用从链表起始位置开始运⾏,如果链表带环则⼀定会在环中相遇,否则快引用率先⾛到链表的末尾。与现实生活中不同,两人相遇有可能是擦肩而过。而引用确实一步一步走的。


为什么要让快引用走两步,慢引用走一步呢?我们想象一种最极限的情况,当fast刚走完一圈时,slow刚进入环内,两个引用的距离差刚好是一个环的距离。当fast与slow每走一次,它们的距离就越接近一个环。
class ListNode{int val;ListNode next;ListNode(int x){val = x;next = null;}
}public class Solution {public boolean hasCycle(ListNode head){ListNode fast = head;ListNode slow = head;while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;if(fast == slow){return true;}}return false;}
}
相关文章:
数据结构(Java版)第八期:LinkedList与链表(三)
专栏:数据结构(Java版) 个人主页:手握风云 目录 一、链表中的经典面试题 1.1. 链表分割 1.2. 链表的回文结构 1.3. 相交链表 1.4. 环形链表 一、链表中的经典面试题 1.1. 链表分割 题目中要求不能改变原来的数据顺序,也就是如上图所示。…...
数据结构学习记录-数据结构概念
1 数据结构: 数据结构是计算机存储,管理数据的方式。 数据必须依据某种逻辑联系组织在一起存储在计算机内 数据结构研究的就是这种数据的存储结构和数据的逻辑结构。 1.1 数据的逻辑结构: 逻辑结构指的是数据本身之间的关系 集合&#x…...
【Linux】11.Linux基础开发工具使用(4)
文章目录 3. Linux调试器-gdb使用3.1 背景3.2 下载安装3.3 使用gdb查询3.4 开始使用 3. Linux调试器-gdb使用 3.1 背景 程序的发布方式有两种,debug模式和release模式 Linux gcc/g出来的二进制程序,默认是release模式 要使用gdb调试,必须…...
数据结构与算法之栈: LeetCode 1047. 删除字符串中的所有相邻重复项 (Ts版)
删除字符串中的所有相邻重复项 https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/ 描述 给出由小写字母组成的字符串 s,重复项删除操作会选择两个相邻且相同的字母,并删除它们在 s 上反复执行重复项删除操作,直到无…...
C++ 在线编译软件介绍、杭电OJ、北大OJ、力扣OJ
在线编译软件的话,可见下: https://www.jyshare.com/compile/12/ 杭州电子科技大学开发的一个免费的写代码地址 ,杭电OJ https://bestcoder.hdu.edu.cn/ 北大OJ http://poj.org/ 力扣OJ 力扣 (LeetCode) 全球极客挚爱的技术成长平台...
Java学习笔记(二十三)
1 CacheEvict CacheEvict是Spring框架中用于清空缓存的注解。以下是对CacheEvict注解的详细介绍: 1.1 作用 CacheEvict注解的主要作用是删除缓存中的数据。在方法执行后或执行前(根据配置),它可以清空指定的缓存项或整个缓存区…...
《AI赋能鸿蒙Next,开启智能关卡设计新时代》
在游戏开发领域,关卡设计是至关重要的一环,它直接影响着玩家的游戏体验和沉浸感。而随着人工智能技术的飞速发展,结合鸿蒙Next系统的强大功能,为游戏的智能关卡设计带来了全新的思路和方法。 利用AI学习玩家行为模式 在鸿蒙Next…...
js:正则表达式
目录 正则表达式的语法 定义 检测 检索 元字符 边界符 量词 字符类 表单判断案例 修饰符 过滤敏感词 正则表达式是一种用于匹配和操作文本的强大工具,它是由一系列字符和特殊字符组成的模式,用于描述要匹配的文本字符组合模式 正则表达式是一…...
linux环境使用docker部署多个war项目
如果你的需求是在一个服务器上部署多个Tomcat项目,并且每个项目需要独立运行,可以通过以下方式实现: 1. 使用不同的端口 每个Tomcat项目可以使用不同的端口号(如9090、9091、9092等),并通过Docker容器分别…...
【react】使用antd Table渲染数据遇到的报错问题
记录自己在开发过程中遇到的报错问题: 目录 原本写法:错误分析:解决方案: 原本写法: render: (text) > {console.log(text, "111111text");console.log(typeof text, "111111text");return t…...
JVM之垃圾回收器G1概述的详细解析
G1(并发) G1 特点 G1(Garbage-First)是一款面向服务端应用的垃圾收集器,应用于新生代和老年代、采用标记-整理算法、软实时、低延迟、可设定目标(最大 STW 停顿时间)的垃圾回收器,用于代替 CMS࿰…...
1.15寒假作业
web:nss靶场ez_ez_php 打开环境,理解代码 使用个体传参的方法,首先代码会检查file参数的前三个字符是不是php,如果是就输出nice,然后用include函数包含file,绕过不是则输出hacker,如果没有file…...
RK356x bsp 5 - 海华AW-CM358SM Wi-Fi/Bt模组调试记录
文章目录 1、环境介绍2、目标3、海华AW-CM358SM3.1、基本信息3.2、支持SDIO3.03.3、电气特性 4、适配流程步骤5、SDIO控制器适配5.1、sdio dts配置5.2、验证 6、Wi-Fi 适配6.1、wifi dts配置6.2、驱动移植6.2.1、kernel menuconfig6.2.2、传统驱动移植6.2.3、RK SDK WIFI/BT驱动…...
支持Google Analytics快捷添加的CMS:费用与部署形式详解
CMS 的费用和部署形式是选择平台的重要参考因素,不同的业务需求需要不同的解决方案。本文将从费用和部署形式两个角度,详细分析支持 Google Analytics 快捷集成的 CMS 和工具,帮助您更好地了解这些平台的特点。 1. BigCommerce 费用ÿ…...
CSS | 实现三列布局(两边边定宽 中间自适应,自适应成比)
目录 示例1 (中间自适应 示例2(中间自适应 示例3(中间自适应 示例4 (自适应成比 示例5(左中定宽,右边自适应 示例6(中间自适应 示例7(中间自适应 示例8(中间定宽…...
fpga系列 HDL:跨时钟域同步 双触发器同步器
目录 **双触发器同步器(Two-Flip-Flop Synchronizer)示例代码**:双触发器同步器的优缺点优点:缺点:适用场景: 应用实例:同步来自spi_slave的单个使能信号 跨时钟域的设计需要特别小心࿰…...
金融项目实战 05|Python实现接口自动化——登录接口
目录 一、代码实现自动化理论及流程 二、脚本实现的理论和准备工作 1、抽取功能转为自动化用例 2、搭建环境(测试工具) 3、搭建目录结构 三、登录接口脚本实现 1、代码编写 1️⃣api目录 2️⃣script目录 2、断言 3、参数化 1️⃣编写数据存储文件:jso…...
《HTML在网络安全中的多面应用:从防范攻击到安全审查》
Html基础 Html简介 HTML(HyperText Markup Language,超文本标记语言)是用于描述网页内容和结构的标准语言。以下是对HTML的简要介绍: 基本概念 定义: HTML不是一种编程语言,而是一种标记语言。 它使用标…...
Linux网络 | 学习传输层网络协议之UDP(短篇)
前言: 本节内容正式迈入传输层网络协议的知识殿堂, 之前的文章, 我们都是在应用层进行翻来覆去。 比如http就是应用层协议, 只不过使用了tcp的系统调用。 从本节开始, 友友们将会学习传输层两大协议: UDP和…...
iOS - 内存屏障的使用场景
内存屏障的使用是为了解决以下几个关键问题: 1. CPU 乱序执行 // 没有内存屏障时,CPU 可能乱序执行 void example() {// 这两行代码可能被 CPU 重排序a 1; // 操作1flag true; // 操作2 }// 使用内存屏障确保顺序 void safeExample() {a 1;…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
