数据结构(Java):单链表面试OJ题

1、题一:获取链表倒数第k个节点

. - 力扣(LeetCode)

1.1 思路解析

此题我们使用双指针法求解。

首先,我们要知道,倒数的第k个节点,距离倒数第一个节点还需要移动k-1次

1.那么我们可以定义出两个指针,分别为fast和slow,他们初始均值均为头结点head

2.先让fast指针向后移动k-1次,slow指针保持不动。

3.接着,fast指针和slow指针同步后移直至fast指针指向最后一个节点。

4.此时,slow指针所指向的位置就是倒数第k个节点。

原理:这个解题思路的原理就是,fast指针和slow指针始终保持着k-1个移动次数,而当fast指针指向最后一个节点(即倒数第一个节点)时,那么slow指针指向的就是倒数第k个节点。

注意事项:

1.k的值是否合法 2.头指针head是否为null

1.2 代码

public int kthToLast(ListNode head, int k) {//当头指针为空时if (head == null) {return Integer.MAX_VALUE;}//当k的值<=0时ListNode cur = head;int size = 0;while (cur != null) {size++;cur = cur.next;}if (k <= 0) {return Integer.MAX_VALUE;}//双指针法求解ListNode fast = head;ListNode slow = head;//先让fast指针移动k-1次int count = 0;while (count != k - 1) {fast = fast.next;//当k值>size时(不合法),fast指针移动的k-1次中,必然会指向nullif (fast == null) {return Integer.MAX_VALUE;}count++;}//slow和fast同步后移,直至fast指向倒数第一个元素(slow和fast始终保持k-1个移动次数)while (fast.next != null) {fast = fast.next;slow = slow.next;}//返回valreturn slow.val;}

2、题二:逆置单链表

. - 力扣(LeetCode)

2.1 思路解析

此题我们使用头插法求解。

这道题的思路很简单:从第二个节点开始,每得到一个节点,将此节点进行头插操作。

注意:要将最开始的头结点的next置为null(因为链表的头节点在逆置后就变成了尾结点)

2.2 代码

public ListNode reverseList(ListNode head) {//当头结点head为空时if (head == null) {return head;}//获取第二个节点,将第一个节点的next置为nullListNode cur = head.next;head.next = null;//头插while (cur != null) {//先获取当前节点的下一个节点ListNode curN = cur.next;//将当前节点的next指向头结点(头插)cur.next = head;//将head更新为新头插的节点head = cur;//更新cur,继续头插cur = curN;}//返回逆置后的头结点return head;}

3、题三:移除链表元素(删除所有某一数值的节点,且一次循环)

. - 力扣(LeetCode)

3.1 思路解析

此题我们使用双指针法求解。

1.我们定义两个指针分别为prev(初始指向head头结点 即第一个节点)和cur(初始指向head的next节点 即第二个节点)。

2.遍历链表。

3.当cur所指节点的值为所要删除的val值时,cur向后移动,prev不动,且将prev的next指针指向移动后的cur,完成节点的删除。

4.若cur所指节点值不是所要删除的val值时,cur和prev同步后移一位。

5.当cur指向null时,遍历完成。

6.经过上述操作,除第一个节点外,其余的节点均已删除完成,我们只需额外判断第一个节点的值是否为要删除的val值即可。

3.2 代码

public ListNode removeElements(ListNode head, int val) {//当head为空时if(head == null) {return head;}//双指针法求解ListNode prev = head;ListNode cur = head.next;while (cur != null) {//判断当前节点的值是否为要删除的val值if (cur.val == val) {//若是,删除节点cur = cur.next;prev.next = cur;}else {//若不是,均向后移动cur = cur.next;prev = prev.next;}}//判断第一个节点的值是否我要删除的val值。if (head.val == val) {head = head.next;}//返回删除后的头结点return head;}

4、题四:获取链表的中间节点

. - 力扣(LeetCode)

 4.1 思路解析

此题我们使用快慢指针法求解。

1.首先,定义两个指针分别为fast和slow。

2.fast指针,每次向后移两位;slow指针,每次向后移一位。

3.链表元素个数为奇数时,当fast.next == null时,slow指向的节点就是中间节点;链表元素个数为偶数时,当fast == null时,slow指向的节点就是中间节点。

注意:

循环结束条件一定要写为:

while(fast != null && fast.next != null)

原因:

1.两者只要有一个不满足就要结束循环,说明已经找到了中间节点

2.一定要fast != null在前,避免fast.next时出现空指针异常

4.2 代码

public ListNode middleNode(ListNode head) {//快慢指针法求解ListNode slow = head;ListNode fast = head;//找中间节点//一定要fast != null在前,避免出现空指针异常//两个条件只要有一个不满足就结束循环,说明到了中间节点的位置while (fast != null && fast.next != null) {ListNode fastN = fast.next;fast = fastN.next;slow = slow.next;}//返回中间节点return slow;}

5、题五:分割链表

给定 x, 把一个链表整理成前半部分小于 x, 后半部分大于等于 x 的形式

链表分割_牛客题霸_牛客网

5.1 思路解析

1.将链表进行遍历

2.将val < x的节点添加到新链表head1中

3.将val >= x的节点添加到新链表head2中

4.将head1和head2进行拼接

5.返回拼接后新表的头结点head1

注意:

1.无论如何,一定要将head2的最后一个节点next域置为null

2.当表中所以元素的val值都大于等于x时,那么head1将为空表,直接返回head2即可

5.2 代码

public ListNode partition(ListNode pHead, int x) {//当pHead为空时if (pHead == null) {return null;}ListNode cur = pHead;ListNode prev = null;ListNode head1 = null;ListNode head2 = null;ListNode cur1 = null;ListNode cur2 = null;//遍历链表 将val < x的节点添加到新表head1中//将val >= x的节点添加到新表head2中while (cur != null) {if (cur.val < x) {if (head1 == null) {head1 = cur1 = cur;}else {cur1.next = cur;cur1 = cur1.next;}}else {if (head2 == null) {head2 = cur2 = cur;}else {cur2.next = cur;cur2 = cur2.next;}}cur = cur.next;}//注意:需要将head2的最后一个节点的next置为nullif(head2 != null) {cur2.next = null;}//如果旧表中所有元素的val值都大于x,那么head1将会是空表,直接返回head2即可if (head1 == null) {return head2;}//将head1和head2进行拼接cur1.next = head2;return head1;}

 6、题六:判断链表是否回文

链表的回文结构_牛客题霸_牛客网

6.1 思路解析

回文结构,其实就是对称结构:

 

当元素个数为奇数时:

1.找到中间节点(使用上面的例题已经讲到)

2.以中间节点为头,逆置其后链表

3.逆置后,链表存在下图结构,指针从两端开始比较val值是否相等,直到相遇时结束,若均相等则为回文结构。

当元素个数为偶数时:

1.偶数时,newH和slow无法相遇

2.我们只需额外判断 当 newH.next == slow 时,说明为回文结构。

6.2 代码

public boolean chkPalindrome(ListNode A) {// write code hereif (A == null) {return true;}ListNode fast = A;ListNode slow = A;//找中间节点while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;}//逆置中间节点后的链表ListNode cur = slow.next;ListNode curN = null;while (cur != null) {curN = cur.next;cur.next = slow;slow = cur;cur = curN;}//从两端开始遍历,比较值是否相等ListNode newCur = A;while (slow != newCur) {if (slow.val != newCur.val) {return false;}if (newCur.next == slow) {return true;}slow = slow.next;newCur = newCur.next;}return true;}

7、题七:相交链表(找出相交节点)

. - 力扣(LeetCode)

7.1 思路解析 

首先,我们要知道,相交链表的形状为Y形,而非X形:

1.遍历求出各链表的长度,并求得长度的差值len。

2.将较长链表的头指针向后移动len个位置。

3.两个链表的头指针同时后移,会在交点处相遇。

7.2 代码

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode curA = headA;ListNode curB = headB;int lenA = 0;int lenB = 0;//求链表1的长度while (curA != null) {lenA++;curA = curA.next;//curA发生改变}//求链表2的长度while (curB != null) {lenB++;curB = curB.next;//curB发生改变}//将curA和curB重新指向链表的起始位置curA = headA;curB = headB;//差值int len = lenA - lenB;//将较长的链表头指针后移差值个长度if (len < 0) {len = -len;while (len != 0) {curB = curB.next;len--;}}else {while (len != 0) {curA = curA.next;len--;}}//相遇处即为交点while (curA != curB) {curA = curA.next;curB = curB.next;}return curA;}

8、题八:判断链表是否带环

. - 力扣(LeetCode)

8.1 思路解析 

此题我们使用快慢指针法求解。

1.定义fast为快指针,一次移动两个位置;slow为慢指针,一次移动一个位置。

2.若链表带环,那么这两个指针必定相遇(追击问题)。

注意:

因为fast一次走两步,slow一次走一步,那进入环中后,每次移动,fast和slow之间的距离必定缩短一个节点,那么必定相遇。

(若每次移动两者间缩短的距离不为1时,那么即使有环,也可能不会相遇)

8.2 代码

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;}

9、题九:求环的入口点

. - 力扣(LeetCode)

9.1 思路解析

设:
起点到入口点的长度为X
相遇节点到入口点长度为Y
环的长度为C

因为fast所走路程为slow所走路程的两倍
故:
X + n*C + (C - Y) = 2*(X + C - Y)
则:
X + (2-n)*C = Y
说明:相遇节点到入口点的距离和起点到入口点的距离相等
则,从相遇节点和起点开始相向而行,相遇时的节点就是入口点

注意:我们还需要处理不是环的情况!!!

9.2 代码

public ListNode detectCycle(ListNode head) {//head为空时if (head == null) {return head;}ListNode fast = head;ListNode slow = head;//确定相遇时的节点while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (fast == slow) {break;}}//不是环if (fast == null || fast.next == null) {return null;}//从起点和相遇节点开始相向而行,相遇的节点就是入口点ListNode curH = head;while (curH != slow) {curH = curH.next;slow = slow.next;}return slow;}

10、题十:合并两个有序链表

. - 力扣(LeetCode)

10.1 思路解析

思路很简单,就是从各链表起点开始遍历,比较val值,谁的值小,就插入到新链表当中。

若某一链表的元素全部插入新链表当中后,将另一链表剩余元素直接拼接即可

10.2 代码

public ListNode mergeTwoLists(ListNode list1, ListNode list2) {//链表为空时if (list1 == null) {return list2;}if (list2 == null) {return list1;}ListNode cur1 = list1;ListNode cur2 = list2;ListNode newH = null;ListNode newCur = null;//从头遍历各链表 谁值小 谁就尾插到新链表中while (cur1 != null && cur2 != null) {if (cur1.val < cur2.val) {if (newH == null) {newH = newCur = cur1;}else {newCur.next = cur1;newCur = newCur.next;}cur1 = cur1.next;}else {if (newH == null) {newH = newCur = cur2;}else {newCur.next = cur2;newCur = newCur.next;}cur2 = cur2.next;}}//某一链表的元素全部插入后,将另一链表剩余元素直接拼接即可if (cur1 == null) {newCur.next = cur2;}if (cur2 == null) {newCur.next = cur1;}return newH;}

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

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

相关文章

SQL去重的四种方法

去重是指&#xff1a;查询的时候, 不显示重复&#xff0c;并不是删除表中的重复项 数据表&#xff1a; 方法1&#xff1a;distinct去重 作用&#xff1a;只能一列去重&#xff0c;当distinct后跟大于1个参数时&#xff0c;他们之间的关系是&&(逻辑与)关系&#xff0c;…

00 Debian字符界面如何支持中文

作者&#xff1a;网络傅老师 特别提示&#xff1a;未经作者允许&#xff0c;不得转载任何内容。违者必究&#xff01; Debian字符界面如何支持中文 《傅老师Debian知识库系列之00》——原创 前言 傅老师Debian知识库特点&#xff1a; 1、拆解Debian实用技能&#xff1b; 2、…

ArcGIS获取21天免费教程,不用自己的邮箱

因为迟迟等不到3.1学习版本&#xff0c;但又很眼馋3.1的功能。 在群友的提醒下&#xff0c;官网免费注册21天试用&#xff0c;注册一次可以用21天&#xff0c;基本全部功能都可以使用。 &#xff08;也有群里的人用PayPal支付&#xff0c;然后设置离线许可&#xff0c;官网退…

Sentinel 学习笔记

Sentinel 学习笔记 作者&#xff1a;王珂 邮箱&#xff1a;49186456qq.com 文章目录 Sentinel 学习笔记[TOC] 前言一、基础概念二、Sentinel控制台2.1 安装控制台2.2 簇点链路2.3 请求限流2.4 线程隔离2.5 服务降级2.6 服务熔断 三、Sentinel客户端3.1 原始Jar包客户端3.2 Sp…

216.Mit6.S081-实验四-Traps

本实验探索如何使用陷阱实现系统调用。您将首先使用栈做一个热身练习&#xff0c;然后实现一个用户级陷阱处理的示例。 开始编码之前&#xff0c;请阅读xv6手册的第4章和相关源文件&#xff1a; kernel/trampoline.S&#xff1a;涉及从用户空间到内核空间再到内核空间的转换的…

【多线程】单例模式

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 单例模式的初识2. 单例模式的含义3. 单例模式实现的两种方式3.1 饿汉模式3.2 懒汉模式3.2.1 懒汉模式(单线…

Redis的缓存雪崩,击穿,穿透的介绍

1.缓存雪崩 为保证缓存中的数据与数据库的数据一致,会给Redis里的数据设置一个过期时间,当缓存数据过期后,用户访问的数据如果不在缓存里,业务系统需要重新生成新的缓存,因为就会访问数据库,并将数据更新到Redis里,这样后续请求就可以直接命中缓存. 当大量缓存在同一时间过期或…

Nginx和Tomcat实现负载均衡群集部署应用

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;Linux高级管理专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️创作时间&…

减少CMOS模拟开关导通电阻引起的失真

1 简介 许多数据采集系统的在多通道间选择时需要使用模拟开关&#xff0c;相比同类的机械开关&#xff0c;半导体开关锁表现出的工作特性是迥然不同的。如&#xff1a;处在闭合位置的CMOS开关的电阻&#xff08;导通电阻 “Ron”&#xff09;会因输入电压的不同而改变。该特性通…

IMU的加速度补偿、祛除向心力

目录 1. 简介2. 仅有XY偏移的修正过程3. 3D修正过程 1. 简介 一般&#xff0c;我们期望用IMU测量某个Target坐标系的加速度、角速度信息&#xff0c;然而IMU的坐标系与Target 坐标系一般存在位姿关系&#xff0c;此时IMU测量的加速度不能直接代表Target左坐标系的加速度。比如…

python库(10):SpaCy库实现NLP处理

1 SpaCy简介 自然语言处理&#xff08;NLP&#xff09;是人工智能领域中一个重要的分支。它旨在使计算机能够理解、解释和生成人类语言。Python中的SpaCy库提供了丰富的功能和工具&#xff0c;SpaCy是一个开源的软件库&#xff0c;用于处理和操作自然语言文本&#xff0c;可以…

BM42:混合搜索的新基准 - Qdrant

在过去的 40 年里&#xff0c;BM25 一直是搜索引擎的标准。它是一种简单但功能强大的算法&#xff0c;已被许多搜索引擎使用&#xff0c;包括 Google、Bing 和 Yahoo。 虽然看起来向量搜索的出现会削弱其影响力&#xff0c;但效果并不明显。目前最先进的检索方法试图将 BM25 与…

python库(11):Box库简化字典和对象之间的转换

1Box库简介 Box是一个Python库&#xff0c;它提供了一种将数据封装在字典和列表中的方式&#xff0c;同时提供了一些额外的功能&#xff0c;比如数据验证、默认值设置等。这使得Box库非常适合用于配置管理、数据传输对象&#xff08;DTO&#xff09;的创建&#xff0c;以及任何…

sqlmap使用之-post注入、head注入(ua、cookie、referer)

1、post注入 1.1、方法一&#xff0c;通过保存数据包文件进行注入 bp抓包获取post数据 将数据保存到post.txt文件 加上-r指定数据文件 1.2、方法二、通过URL注入 D:\Python3.8.6\SQLmap>python sqlmap.py -u "http://localhost/login.php" --data "userna…

替换:show-overflow-tooltip=“true“ ,使用插槽tooltip,达到内容可复制

原生的show-overflow-tooltip“true” 不能满足条件&#xff0c;使用插槽自定义编辑&#xff1b; 旧code <el-table-column prop"reason" label"原因" align"center" :show-overflow-tooltip"true" /> <el-table-column pro…

压缩文件的解析方式

Java中我们用ZipInputStream和ZipOutputStream来完成对zip文件和rar文件的读写 I /O流&#xff1a; Input:输入&#xff0c;通过“输入流”进行文件的读取操作 output:输出&#xff0c;通过“输出流”进行文件的写入操作 一、将压缩包解压缩 1.解压缩.zip格式文件&#xf…

微信小程序毕业设计-汽车维修项目管理系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

NoSQL 之Redis集群模式

一&#xff1a;Redis集群方式 Redis有三种模式&#xff1a;分别是主从复制、哨兵模式、Cluster 1&#xff1a;主从模式: 主从复制是高可用Redis的基础&#xff0c;哨兵和群集都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份&#xff0c;以及对于读操作的…

netscaler LDAP+RADIUS传统的双因素认证方式(之一)

如果使用传统的双因素认证方式&#xff0c;可以通过在Citrix ADC (NetScaler) 13.1上配置Gateway Virtual Server来实现LDAP和RADIUS的双因素认证。当前配置方式&#xff0c;采用Cateway vServer两个Basic Authtication Policy方式实现&#xff0c;以下是详细步骤&#xff1a; …

【码题集】习题

目录 史莱姆融合 松鼠接松果 新月轩就餐 史莱姆融合 根据题意就是一道集合合并的题&#xff0c;所以要用并查集&#xff0c;不过最后我们要输出整个序列&#xff0c;所以要在合并的时候维护一个链表&#xff0c;以便最终合并成一个大集合的时候&#xff0c;输出整个链表就是…