数据结构:LinkedList与链表—面试题(三)
目录
1、移除链表元素
2、反转链表
3、链表的中间结点
4、返回倒数第k个结点
5、合并两个有序链表
1、移除链表元素
习题链接
https://leetcode.cn/problems/remove-linked-list-elements/description/
描述:给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

这道题大家看着是不是十分的眼熟,这其实就是我们在讲解无头单向链表时进行的一个方法的模拟实现
首先这道题我们要先进行头节点的判断如果头节点为空就代表链表为空,没有数据直接返回null
如果不为空,我们要创建两个指针,一个指向头结点(prev),一个指向头节点的下一个结点(cur),然后让cur不断的往前走,在走的过程中进行判断,如果cur的值不等于我们要删除的值就让prev移动到目前cur的位置,之后cur继续走如果cur的值等于我们要删除的数,居然prev的后继结点变成此时cur的后继结点,以达到删除结点的目的
完整代码
class Solution {public ListNode removeElements(ListNode head, int val) {if(head == null){return null;}ListNode cur = head.next;ListNode perv = head;while(cur != null){if(cur.val == val){perv.next = cur.next;}else{perv = cur;}cur = cur.next;}if(head.val == val){head = head.next;}return head;}
}
2、反转链表
习题链接
https://leetcode.cn/problems/reverse-linked-list/description/
描述:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。


首先我们依然要进行头结点的判断,但是这次我们又加了一个判断因为我们这次是要将一个链表进行反转,而当我们的链表只有一个数时,进行反转后的链表依旧跟原来一样,因此当头节点的下一个为空时即链表只有一个数,就直接返回头结点即可。
然后这次我们依然要创建一个指针指向头结点的下一个结点(cur),因为这次我们是反转链表我们的头节点将会变成最后一个结点,而最后有一个结点是没有后继结点的,因此我们要将头节点的后继置为空。
之后我们不断让cur往后走,并在循环中创建一个新的指向(curN)令他指向cur的下一个结点,这时我们让cur的下一个结点变成头节点,之后在将cur变成头节点,然后我们在让cur指针指向curN处,而进行新的循环时curN因为cur的改变会往后走一个结点这样就实现了cur的移动和链表的反转。

完整代码
class Solution {public ListNode reverseList(ListNode head) {if(head == null){return null;}if(head.next == null){return head;}ListNode cur = head.next;head.next = null;while(cur != null){ListNode curN =cur.next;cur.next = head;head = cur;cur = curN;}return head;}
}
3、链表的中间结点
习题链接
https://leetcode.cn/problems/middle-of-the-linked-list/description/描述:给你单链表的头结点 head ,请你找出并返回链表的中间结点。如果有两个中间结点,则返 回第二个中间结点。

在这里我们用到了一个我们在做题时经常会使用到的一个方法:快慢指针。
所谓快慢指针其实就是让两个指针以同时移动但他们每次移动的距离是不同的这样就使得两个指针移动速度变得不同。
在这道题里我们使用的就是这种方法:首先我们设立两个指针,快指针(fast)和慢指针(slow)让他们指向头节点。
那么我们该怎样利用这两个指针找到中间结点呢?
我们来上面这两个事例,当这两个指针都在头节点时,我们让fast指针每次走两步,让slow指针每次走一步,当fast指针走到链表尽头时,即fast为空和fast的下一个结点为空时,结束移动,这时当我们结束移动后,会发现我们的slow指针正处于我们要找的中间结点位置

完整代码
class Solution {public ListNode middleNode(ListNode head) {ListNode fast = head;ListNode slow = head;while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;}return slow;}
}
4、返回倒数第k个结点
习题链接
https://leetcode.cn/problems/kth-node-from-end-of-list-lcci/description/
描述:实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

对于这道题他让我们去求倒数第k个结点的值,在这里我们有一种方法来解决这个问题。
首先我们求出这个链表的长度,我们再用我们求出的长度减去k,这时根据得到的数,我们让一个指针从头结点走这个数的步,我们会发现最后停下的这个结点值正是倒数第k个结点的值。

完整代码
class Solution {public int kthToLast(ListNode head, int k) {ListNode cur = head;int count = 0;while(cur != null){count++;cur = cur.next;}ListNode fast = head;int n = count-k;while(n != 0){fast = fast.next;n--;}return fast.val;}
}
5、合并两个有序链表
习题链接
https://leetcode.cn/problems/merge-two-sorted-lists/description/描述:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所 有节点组成的。

在这里我们用到了一个我们经常使用的方法:创建一个虚拟头结点
在这道题里我们先创建一个虚拟头结点node,在创建一个指针tmp指向虚拟头结点
我们发现这道题的要求是将两个升序链表合并为一个新的 升序 链表,所以我们需要进行大小的比较,因此在这里我们先创建一个循环,在循环中进行比较,让list1链表的值小于list2时就让tmp的后继变成这时list1,然后让list1往后走,反之就让tmp的后继变成这时list2,然后让list2往后走,并且,每比较一次就让tmp往后走一步,这样就成功实现了大小的比较和,两个链表的合并,但是这里我们需要注意一点,如果有一个链表先走完了,我们就可以让另一个链表剩下的值直接链接在tmp后边。最后返回从虚拟头节点的下一个结点返回链表,这时的链表就是我们新的 升序 链表

完整代码
class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode node = new ListNode(-1);ListNode tmp = node;while(list1 != null && list2 != null){if(list1.val < list2.val){tmp.next = list1;list1 = list1.next;}else{tmp.next = list2;list2 = list2.next;}tmp = tmp.next;}if(list1 == null){tmp.next = list2;}if(list2 == null){tmp.next = list1;}return node.next;}
}
6、分割链表
习题链接
https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId=8&&tqId=11004&rp=2&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking描述:现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。
首先我们创建两个虚拟头结点,并用两个指针指向他们,根据题目意思我们要将所有小于x的数放到一边,大于等于的放到另一边,并且不改变他们的顺序,这样的话我们利用排序肯定是不可以了,因此我们利用了虚拟头节点的办法,我们将小于x的放到一个链表当中,大于等于x的放到另一个链表中,最后在让这两个链表链接在一起,这样就成功的分割了链表
注意:在最后我们要将存放大于等于x的链表最后一个结点的后继如果不等于空就要置为空。
如果小于x 的链表为空,我们可以直接返回大于等于x的链表。
完整代码
public class Partition {public ListNode partition(ListNode pHead, int x) {ListNode head1 = new ListNode(-1);ListNode head2 = new ListNode(-2);ListNode cur = head1;ListNode prev = head2;ListNode node = pHead;while(node != null){if(node.val < x){cur.next = node;cur = cur.next;}else{prev.next = node;prev = prev.next;}node = node.next;}cur.next = head2.next;if(head2.next != null){prev.next = null;}if(head1.next == null){return head2.next;}return head1.next;}
}
7、链表的回文结构
习题链接
https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId=49&&tqId=29370&rp=1&ru=/activity/oj&qru=/ta/2016test/question-ranking
描述:对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
根据题意我们直到我们要判断链表是否为回文链表,我们当为空和只有一个数时都是回文结构,因此要先进行判断,之后我直到回文结构代表链表一半和另一半的反转时相同的,因此我们发现这时我们上面讲的反转链表和求中间结点的结合,所以这题的思路就是找到中间结点,讲中间结点和之后的结点进行反转最后在与另一半进行比较每个结点的值如果出现一个不等就代表不是回文结构,如果另一个链表的下一个值,等于我们反转后最后一个值直接就可以范围true

完整代码
public class PalindromeList {public boolean chkPalindrome(ListNode A) {if(A == null || A.next ==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;while(cur != null ){ListNode curN = cur.next;cur.next = slow;slow = cur;cur = curN;}while(A != slow){if(A.val != slow.val){return false;}if(A.next == slow){return true;}A = A.next;slow = slow.next;}return true;}
}
8、相交链表
习题链接
https://leetcode.cn/problems/intersection-of-two-linked-lists/
描述:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
首先我们创建两个指针cur1和cur2,令他们分别指向head1和head2,这道题要我们判断两个链表存不存在相交结点,但是我们知道这两个可能长度是不相同的这就会导致在他们相交前是不一样长的因此,我们要先求出这两个链表的长度差,然后让长的链表先走差值步,令他们在同一个起跑线上,在一步一步的走,同时进行判断,如果走到最后都没有相等就代表没有相交
完整代码
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode cur1 = headA;ListNode cur2 = headB;int count1 = 0;while(cur1 != null){cur1 = cur1.next;count1++;}int count2 = 0;while(cur2 != null){cur2 = cur2.next;count2++;}cur1 = headA;cur2 = headB;int count3 = count1-count2;if(count3 < 0){cur1 = headB;cur2 = headA;count3 = count2 -count1;}while(count3 != 0){cur1 = cur1.next;count3--;}while(cur1 != cur2){cur1 = cur1.next;cur2 = cur2.next;}if(cur1 == null){//当走到最后链表会为空,但这时他们会相等,因此跳出循环,所以我们要先判 //断是否是走到尽头引起的相等,如果是就返回null,如果不是就往下执行truereturn null;}return cur1;}
}
9、环形链表
习题链接
https://leetcode.cn/problems/linked-list-cycle/description/描述:
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。

这道题利用了快慢指针法,根据题意他要判断是否为环形链表,如果他是环形的话我们发现如果我们利用快慢指针,让一个指针一次走两步一个一次走一步,当慢指针进环的时候最好的情况下很快就会相遇,最坏的情况下是他们直接的距离是环的长度,但因为慢指针一次走一步快指针一次走两步,没动一次他们间的距离就会减少一步,因此他们一定会相遇,所以,如果他们相遇就代表有环,如果快指针走到最后为空就代表没有环
注意:当链表为空和只有一个结点时也是没有环的。
完整代码
public class Solution {public boolean hasCycle(ListNode head) {if(head == null || head.next == null){return false;}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;}
}
10、环形链表II
习题链接
https://leetcode.cn/problems/linked-list-cycle-ii/description/
描述:
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改链表。

这道题让我们去求环的入口点,首先我们来看下面这张图

我们知道当我们进行环的判断时会有一个相遇点(M),我们假设入口点(E)到相遇点的距离为x,环的总长为R, 而链表的头结点到入口点的距离为L,根据上题我们知道两个指针在相遇前快指针可能已经走了n圈,所以快指针走的路程为L+x+nR,慢指针走的路程为L+x,而快指针是以慢指针的2倍前进的,因此他们相遇时快指针的的路程是慢指针的两倍,因此我们得出2*(L+x)=L+x+nR
当我们化简后发现L= nR-x,而我们的n取决于fast走的圈数,但是当我们以n=1来看时,我们发现L的长度就等于R-X(L=R-x是一定的,n的形成只是由于指针速度不同所导致的),这时我们发现如果有两个指针从头节点和相遇点一起走当他们相遇时的相遇结点就是我们的入口点
完整代码
public class Solution {public ListNode detectCycle(ListNode head) {if(head == null || head.next == null){return null;}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;}fast = head;while(fast != slow){fast = fast.next;slow = slow.next;}return fast;}
}
好了今天的分享就到这里了,还请大家多多关注,我们下一篇见!
相关文章:
数据结构:LinkedList与链表—面试题(三)
目录 1、移除链表元素 2、反转链表 3、链表的中间结点 4、返回倒数第k个结点 5、合并两个有序链表 1、移除链表元素 习题链接https://leetcode.cn/problems/remove-linked-list-elements/description/ 描述:给你一个链表的头节点 head 和一个整数 val ÿ…...
【开发日记】Docker修改国内镜像源
1、问题: docker pull镜像时提示以下内容: Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)2、解决 ①…...
Elasticsarch:使用全文搜索在 ES|QL 中进行过滤 - 8.17
8.17 在 ES|QL 中引入了 match 和 qstr 函数,可用于执行全文过滤。本文介绍了它们的作用、使用方法、与现有文本过滤方法的区别、当前的限制以及未来的改进。 ES|QL 现在包含全文函数,可用于使用文本查询过滤数据。我们将回顾可用的文本过滤方法…...
第432场周赛:跳过交替单元格的之字形遍历、机器人可以获得的最大金币数、图的最大边权的最小值、统计 K 次操作以内得到非递减子数组的数目
Q1、跳过交替单元格的之字形遍历 1、题目描述 给你一个 m x n 的二维数组 grid,数组由 正整数 组成。 你的任务是以 之字形 遍历 grid,同时跳过每个 交替 的单元格。 之字形遍历的定义如下: 从左上角的单元格 (0, 0) 开始。在当前行中向…...
RK3399开发板Linux实时性改造
本次测试基于NanoPC-T4开发板(国产化处理器RK3399),4.19.111内核Xenomai实时性改造测试。 Xenomai下载网站:https://xenomai.org/downloads/ NanoPC-T4网站:https://wiki.friendlyarm.com/wiki/index.php/NanoPC-T4/z…...
青少年编程与数学 02-006 前端开发框架VUE 22课题、状态管理
青少年编程与数学 02-006 前端开发框架VUE 22课题、状态管理 一、状态管理二、Vuex1. 安装Vuex2. 创建Vuex Store3. 在Vue应用中使用Store4. 在组件中使用状态5. 模块化Store 三、Vuex应用示例1. 创建项目2. 安装Vuex3. 设置Vuex Store4. 在主项目中使用Store5. 创建组件6. 更新…...
Linux 内核中的 netif_start_queue 函数:启动网络接口发送队列的关键
在 Linux 内核的网络子系统中,netif_start_queue 函数扮演着至关重要的角色。这个函数的主要功能是启动(或启用)网络接口的发送队列,标志着网络接口已经准备好开始发送数据包。本文将深入探讨 netif_start_queue 函数的用途、工作原理以及在实际网络驱动代码中的应用。 函…...
数据结构之顺序结构二叉树(超详解)
文章目录 1 树1.1 树的概念与结构1.2 相关术语1.3 树的表示与运用场景1.3.1 运用场景 2. 二叉树2.1 概念与结构2.1.1 满二叉树2.1.2 完全二叉树 3. 顺序结构二叉树3.1 堆的引入3.1.1 概念与结构 3.2 功能实现3.2.1 堆的结构3.2.2 初始化、销毁 3.3 堆的插入数据3.3.1 向上调整算…...
acwing_5722_十滴水
acwing_5722_十滴水 下面这篇大佬的题解属实是把指针用明白了,可以好好理解一下: 原题解连接:AcWing 5722. 一个简单模拟实现 - AcWing map/unordered_map的用法:见收藏夹 #include<iostream> #include<unordered_map> #incl…...
acwing-3194 最大的矩形
acwing-3194 最大的矩形 这个题程序设计课上有讲过, 平民算法,时间复杂度在 O ( n 2 ) O(n^2) O(n2) // // Created by HUAWEI on 2024/10/28. // #include<iostream>using namespace std;const int Max_size 1e4 20;int N; int h[Max_size];…...
UnityDemo-TheBrave-制作笔记
这是我跟着b站up主MStudio的视频学习制作的,大体上没有去做一些更新的东西,这里只是一个总的总结。在文章的最后,我会放上可以游玩该游戏的链接和exe可执行文件,不过没有对游戏内容进行什么加工,只有基本的功能实现罢了…...
玩转 JMeter:Random Order Controller让测试“乱”出花样
嘿,各位性能测试的小伙伴们!今天咱要来唠唠 JMeter 里超级有趣又超实用的 Random Order Controller(随机顺序控制器),它就像是性能测试这场大戏里的“魔术棒”,轻轻一挥,就能让测试场景变得千变…...
VTK知识学习(33)-交互问题2
1、前言 主要是针对前面有过实现不了交互的情况进行说明,经过一些尝试和分析调用API,总算实现RenderWindowControl函数回调正常串接,当然这个移动处理事件的效果目前也没有确认。 2、使用 vtkImageReslice reslice vtkImageReslice.New();p…...
Centos9-SSH免密登录配置-修改22端口-关闭密码登录-提高安全性
Centos9-SSH免密登录配置-修改22端口-关闭密码登录 生成秘钥对将公钥信息存进authorized_keys测试登录查询访问记录、比对指纹更换22访问端口关闭账号密码登录生成秘钥对 生成密钥对,指定 备注 和 文件目录命令执行后,默认两次回车,不设置秘钥使用密码ssh-keygen -t rsa -b …...
SqlServer: An expression services limit has been reached异常处理
在工作中遇到一个问题,因为项目很老,代码很不规范,出现一种场景: 查询所有客户(5w条以上),然后根据客户Id,再去其他表查询,代码中是直接将customerId拼接到sql中去查询,形成的sql如…...
CentOS下安装Docker
Docker 必须要在Linux环境下才能运行,windows下运行也是安装虚拟机后才能下载安装运行,菜鸟教程 下载安装 linux 依次执行下边步骤 更新 yum yum update 卸载旧的Docker yum remove docker docker-client docker-client-latest docker-common doc…...
WPF控件Grid的布局和C1FlexGrid的多选应用
使用 Grid.Column和Grid.Row布局,将多个C1FlexGrid布局其中,使用各种事件来达到所需效果,点击复选框可以加载数据到列表,移除列表的数据,自动取消复选框等 移除复选框的要注意!!!&am…...
Jenkins-持续集成、交付、构建、部署、测试
Jenkins-持续集成、交付、构建、部署、测试 一: Jenkins 介绍1> Jenkins 概念2> Jenkins 目的3> Jenkins 特性4> Jenkins 作用 二:Jenkins 版本三:DevOps流程简述1> 持续集成(Continuous Integration,CI࿰…...
高级第一次作业
1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容,不存在则创建一个文件将创建时间写入。 2、写一个 shel1 脚本,实现批量添加 20个用户,用户名为user01-20,密码为user 后面跟5个随机字符。 3、编写个shel 脚本将/usr/local 日录下大于10M的文件转移到…...
Copula算法原理和R语言股市收益率相依性可视化分析
阅读全文:http://tecdat.cn/?p6193 copula是将多变量分布函数与其边缘分布函数耦合的函数,通常称为边缘。在本视频中,我们通过可视化的方式直观地介绍了Copula函数,并通过R软件应用于金融时间序列数据来理解它(点击文…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...

