【数据结构】单链表面试题(Java + 力扣 + 详解)

🎇🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!
人生格言: 当你的才华撑不起你的野心的时候,你就应该静下心来学习!
欢迎志同道合的朋友一起加油喔 💪💪💪
目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个🐒嘿嘿
谢谢你这么帅气美丽还给我点赞!比个心

链表面试题

  • 一、移除链表元素
    • 1. 题目
    • 2. 解析
    • 3. 完整代码展示
  • 二、反转链表
    • 1. 题目
    • 2. 解析
    • 3. 完整代码展示
  • 三、链表的中间结点
    • 1. 题目
    • 2. 解析
    • 3. 完整代码展示
  • 四、 链表中倒数第k个节点
    • 1. 题目
    • 2. 解析
    • 3. 完整代码展示
  • 五、合并两个有序链表
    • 1. 题目
    • 2. 解析
    • 3. 完整代码展示

一、移除链表元素

203.移除链表元素

1. 题目


在这里插入图片描述


2. 解析


  • 特殊情况处理:
  • 如果链表头节点 head 为空,直接返回 null,表示链表为空,无需处理。
if(head == null){return null;
}

在这里插入图片描述

  • 一般情况处理:
  • 定义两个指针,prevNode 指向当前节点前一个节点(初始为头节点)cur 指向当前节点下一个节点
ListNode prevNode = head;
ListNode cur = head.next;
  • 循环遍历链表:
  • 使用 cur 指针遍历链表,当 cur 不为 null 时执行循环。
  • 如果 cur 指向的节点的值等于 val,则将 prevNode.next 指向 cur.next,即跳过当前节点 cur
  • 否则,更新 prevNode 为 cur,并将 cur 移动到下一个节点。
while(cur != null){if(cur.val == val){prevNode.next = cur.next;cur = cur.next;}else{prevNode = cur;cur = cur.next;}
}
  • 处理头节点:
  • 最后处理头节点,如果头节点的值等于 val,则将头节点 head 指向下一个节点,即跳过头节点。
if(head.val == val){head = head.next;
}
  • 返回链表头:
  • return head; 返回处理后的链表头节点。

3. 完整代码展示


/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode removeElements(ListNode head, int val) {//特殊情况、链表为空if(head == null){return null;}//处理一般情况//定义两个指针,prev 指向第一个节点,cur 指向第二个节点ListNode prevNode = head;ListNode cur = head.next;//循环判断条件 cur != null//先不考虑 头节点//从第二个节点开始排查while(cur != null){if(cur.val == val){prevNode.next = cur.next;cur = cur.next;}else{prevNode = cur;cur = cur.next;}}//最后处理头节点if(head.val == val){head = head.next;}return head;}
}

二、反转链表

206.反转链表


1. 题目


在这里插入图片描述


2. 解析

  • 要求:遍历链表一遍就反转完
  • 思路:
  • 先把原链表的头节点的next置为空,记录好下一个节点,进行头插

在这里插入图片描述


  • reverseList 方法用于反转单链表,接收一个头节点 head 作为参数,并返回反转后的新头节点。

  • 首先进行了几个边界条件的判断:

     如果 head 为 null,即空链表,直接返回 null。如果链表只有一个节点 (head.next == null),则直接返回 head,因为反转后还是自身。
    
  • 若链表节点数大于1,进入反转过程:

    ListNode cur = head.next; 初始化 cur 为 head 的下一个节点。
    head.next = null; 将 head 的 next 指针置为 null,表示反转后的尾节点。
    
  • 使用头插法反转链表:

    while (cur != null) 循环直到 cur 为 null:
    ListNode curNext = cur.next; 记录当前节点 cur 的下一个节点。
    

    cur.next = head; 将 cur 的 next 指向 head,完成头插操作。
    head = cur; 更新 head 为当前 cur,即新的头节点。
    cur = curNext; 将 cur 移动到下一个节点,继续反转操作。

  • 最终返回 head,此时 head 已经是反转后链表的新头节点。

  • 这种方法的时间复杂度为 O(n),其中 n 是链表的节点数,因为需要遍历整个链表一次来完成反转操作。


3. 完整代码展示

/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
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 curNext = cur.next;cur.next = head;head = cur;cur = curNext;}return head;}
}

三、链表的中间结点

876.链表的中间结点


1. 题目


在这里插入图片描述


2. 解析


  • 第一种解法:长度 / 2

但是这种 需要遍历一遍链表,还要再除以2,可以在这个基础上进行优化

  • 第二种解法:

定义两个指针:(快慢指针)fast快指针 slow慢指针


在这里插入图片描述


算法采用了快慢指针技巧:

  • fast 指针每次移动两步:fast = fast.next.next;
  • slow 指针每次移动一步:slow = slow.next;

由于 fast 指针移动速度是 slow 指针的两倍,所以当 fast 指针到达链表末尾时,slow 指针恰好指向链表的中间节点。

具体执行过程如下:

  • 初始时,fastslow 都指向链表的头节点 head

  • 在每一轮循环中,首先检查 fast 是否为空且 fast.next 是否为空(即 fast 是否到达链表尾部)

    如果是,则退出循环,此时 slow 指向链表的中间节点。
    如果不是,则将 fast 向前移动两步,将 slow 向前移动一步。
    
  • 循环结束后,返回 slow,即为链表的中间节点。

  • 这段代码的时间复杂度为 O(n),其中 n 是链表的长度,因为 fast 指针最多遍历链表一次。空间复杂度为 O(1),因为只使用了常量级的额外空间用于两个指针。


3. 完整代码展示


/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
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;}
}

四、 链表中倒数第k个节点

链表中倒数第k个节点

1. 题目


在这里插入图片描述


2. 解析


  • 定义了一个简单的链表节点类 ListNode,每个节点包含一个整数值 val 和一个指向下一个节点的引用 next

  • indKthToTail(ListNode head, int k) 方法接收一个链表头节点 head 和一个整数 k,表示要查找倒数第k个节点。
  • 首先,使用两个指针 fast 和 slow,初始化都指向头节点 head
  • fast 先移动 k 步,如果 k 大于链表长度,则直接返回 null
  • 然后,fastslow 同时向前移动,直到 fast 到达链表末尾,此时 slow 指向的即为倒数第 k 个节点。
  • 返回 slow。

  • 在 main 方法中,创建了一个包含五个节点的链表。
  • 分别测试了找倒数第1个、第3个节点以及超过链表长度的情况。

3. 完整代码展示

// 定义链表节点类
class ListNode {int val;ListNode next;ListNode(int x) {val = x;}
}public class Solution {public ListNode FindKthToTail(ListNode head, int k) {if (head == null || k <= 0) {return null;}ListNode fast = head;ListNode slow = head;// 快指针先向前移动k步for (int i = 0; i < k; i++) {if (fast != null) {fast = fast.next;} else {// 如果k超过了链表长度,直接返回nullreturn null;}}// 快慢指针一起向前移动,直到快指针到达链表末尾while (fast != null) {fast = fast.next;slow = slow.next;}// 此时slow指向的就是倒数第k个节点return slow;}// 测试代码public static void main(String[] args) {Solution solution = new Solution();// 创建链表:1 -> 2 -> 3 -> 4 -> 5ListNode head = new ListNode(1);head.next = new ListNode(2);head.next.next = new ListNode(3);head.next.next.next = new ListNode(4);head.next.next.next.next = new ListNode(5);// 测试找倒数第1个节点ListNode result = solution.FindKthToTail(head, 1);if (result != null) {System.out.println(result.val); // 输出5} else {System.out.println("找不到节点");}// 测试找倒数第3个节点result = solution.FindKthToTail(head, 3);if (result != null) {System.out.println(result.val); // 输出3} else {System.out.println("找不到节点");}// 测试k超过链表长度result = solution.FindKthToTail(head, 6);if (result != null) {System.out.println(result.val);} else {System.out.println("找不到节点"); // 输出找不到节点}}
}

五、合并两个有序链表

21.合并两个有序链表


1. 题目

在这里插入图片描述


2. 解析


  • 虚拟节点的创建:
ListNode newNode = new ListNode(1);

这里创建了一个值为 1 的虚拟节点 newNode。这个虚拟节点的作用是作为合并后链表的头节点的前一个节点,简化了链表操作。

  • 临时节点:
ListNode tmp = newNode;

tmp 节点用来迭代构建合并后的链表,最初指向 newNode,随着节点的合并不断移动。

  • 合并过程:

使用 while 循环,只要 list1 和 list2 都不为 null,比较它们当前节点的值:
如果 list1.val < list2.val,将 tmp.next 指向 list1,然后 list1 向后移动一位,tmp 也向后移动一位。
否则,将 tmp.next 指向 list2,然后 list2 向后移动一位,tmp 也向后移动一位。

  • 处理剩余节点:

循环结束后,可能会有一个链表还有剩余节点未合并,使用两个 if 条件分别处理:
如果 list1 不为 null,将剩余的 list1 接在 tmp.next 后面。
如果 list2 不为 null,将剩余的 list2 接在 tmp.next 后面。
返回合并后链表的头节点:返回 newNode.next,即虚拟节点 newNode 的下一个节点,即合并后的链表的头节点。

  • 总结

这段代码通过使用虚拟节点和临时节点,在一次遍历中将两个有序链表 list1 和 list2 合并为一个有序链表,并返回合并后链表的头节点。

3. 完整代码展示

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {//创建一个虚拟节点ListNode newNode = new ListNode(1);//临时节点ListNode tmp = newNode;while(list1 != null && list2 != null){if(list1.val < list2.val){tmp.next = list1;list1 = list1.next;tmp = tmp.next;}else{tmp.next = list2;list2 = list2.next;tmp = tmp.next;}}if(list1 == null){tmp.next = list2;}if(list2 == null){tmp.next = list1;}return newNode.next;}
}

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

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

相关文章

动态代理更改Java方法的返回参数(可用于优化feign调用后R对象的统一处理)

动态代理更改Java方法的返回参数&#xff08;可用于优化feign调用后R对象的统一处理&#xff09; 需求原始解决方案优化后方案1.首先创建AfterInterface.java2.创建InvocationHandler处理代理方法3. 调用 实际运行场景拓展 需求 某些场景&#xff0c;调用别人的方法&#xff0…

Chapter 15 Python函数进阶

欢迎大家订阅【Python从入门到精通】专栏&#xff0c;一起探索Python的无限可能&#xff01; 文章目录 前言一、函数多返回值二、函数的多种传参方式三、匿名函数 前言 在Python中&#xff0c;函数是组织代码、提高重用性与可读性的基本构建块。随着程序逻辑的复杂性增加&…

在 Windows 上安装 PostgreSQL

官网下载地址&#xff1a; https://www.enterprisedb.com/downloads/postgres-postgresql-downloadsWindows平台 官网直接提供exe安装包&#xff0c;没有手动安装的压缩包 postgresql-14.4-1-windows-x64.exe几个重要的安装选项 安装界面会指定服务程序和库两个路径&#xf…

压测实操--kafka-consumer压测方案

作者&#xff1a;九月 环境信息&#xff1a; 操作系统centos7.9&#xff0c;kafka版本为hdp集群中的2.0版本。 Consumer相关参数 使用Kafka自带的kafka-consumer-perf-test.sh脚本进行压测&#xff0c;该脚本参数为&#xff1a; thread&#xff1a;测试时的单机线程数&…

刷机维修进阶教程-----何谓“tee损坏” 指纹丢失 掉帧 传感器失效?详细修复步骤教程

TEE损坏指的是安卓机型中Key Attestation密钥认证所依赖的可信应用中的证书库被破坏了。然后拒绝为指纹密匙认证提供服务。加密的密匙由TEE负责管理。tee损坏只影响当前机型的密匙认证。不影响加密。通俗的理解。如果你机型维修或者刷机或者解锁或者格机 全檫除分区等等后有异常…

Elasticsearch集群配置-节点职责划分 Hot Warm 架构实践

前言 本文主要讲了ES在节点部署时可以考虑的节点职责划分&#xff0c;如果不考虑节点部署&#xff0c;那么所有节点都会身兼数职&#xff08;master-eligible &#xff0c;data&#xff0c;coordinate等&#xff09;&#xff0c;这对后期的维护拓展并不利&#xff0c;所以本文…

软件测试10 渗透性测试及验收测试

渗透性测试及验收测试 知识回顾 Web UI自动化测试 引入自动化测试需要满足的条件自动化测试流程简述自动化测试的关键技术Selenium页面元素定位方式 目标 了解安全测试的概念了解常见的安全漏洞了解安全测试流程及测试工具的使用理解验收测试的概念掌握Alpha测试和Beta测试…

【React 】开发环境搭建详细指南

文章目录 一、准备工作1. 安装 Node.js 和 npm2. 选择代码编辑器 二、创建 React 项目1. 使用 Create React App2. 手动配置 React 项目 三、集成开发工具1. ESLint 和 Prettier2. 使用 Git 进行版本控制 在现代前端开发中&#xff0c;React 是一个非常流行的框架&#xff0c;用…

【计算机毕业设计】866校企合作管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Git处理Failed to connect to www.google.com port 80: Timed out

Git处理Failed to connect to www.google.com port 80: Timed out 输入提交代码命令&#xff1a;git push -u origin master 报错&#xff1a;fatal: unable to access https://gitee.com/solitudeYu/gerenzhuye.git/: Failed to connect to www.google.com port 80: Timed ou…

AI数字人+城市交通大数据可视化平台,让交通管理与服务更简便、更智能

如今&#xff0c;AI数字人作为科技革命和产业革命的重要驱动力&#xff0c;AI数字人接入城市交通大数据可视化平台&#xff0c;可以有效地将各硬件与业务系统进行深度融合&#xff0c;完成业务闭环。依托AI数字人的应用&#xff0c;使城市交通大数据可视化平台的使用复杂度大幅…

我在Vscode学Java泛型(泛型设计、擦除、通配符)

Java泛型 一、泛型 Generics的意义1.1 在没有泛型的时候&#xff0c;集合如何存储数据1.2 引入泛型的好处1.3 注意事项1.3.1 泛型不支持基本数据类型1.3.2 当泛型指定类型&#xff0c;传递数据时可传入该类及其子类类型1.3.3 如果不写泛型&#xff0c;类型默认是Object 二、泛型…

Elastic 数据分层策略:为弹性及高效的实施而优化

作者&#xff1a;来自 Elastic Michael Calizo, Tim Lee 在 Elastic&#xff0c;我们大多数成功的客户实施都是从单一用例开始的&#xff0c;旨在满足特定的业务需求。Elastic 最初被采用通常是因为开发人员欣赏它提供的功能。然而&#xff0c;由于其灵活性和可定制性&#xff…

Ubuntu安装QQ教程

Ubuntu安装QQ教程 腾讯更新Linux版的QQ&#xff0c;这里安装一下&#xff1b; 首先&#xff0c;进入官网找到合适对应的安装包&#xff1b; QQLinux版本官网&#xff1a;https://im.qq.com/linuxqq/index.shtml 我们是ubuntu系统选择X86下的deb版本&#xff0c;如果是arm开…

ROS参数服务器增删改查实操C++

ROS参数服务器增删改查实操C 创建功能包参数服务器新增&#xff08;修改&#xff09;参数参数服务器获取参数参数服务器删除参数 ROS通信机制包括话题通信、服务通信和参数服务器三种通信方式&#xff0c;各原理及代码实现如下表 功能博客链接说明VScode配置 ROS 环境VScode创建…

【Vue实战教程】之Vuex状态管理详解

Vuex状态管理 1 Vuex简介 1.1 什么是Vuex Vuex是一个专为Vue.js应用程序开发的状态管理工具。它采用了集中式存储管理应用的所有的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 简单来说&#xff0c;Vuex是一个适用于在Vue项目开发时使用的状态管理…

机器学习 | 回归算法原理——多项式回归

Hi&#xff0c;大家好&#xff0c;我是半亩花海。接着上次的最速下降法&#xff08;梯度下降法&#xff09;继续更新《白话机器学习的数学》这本书的学习笔记&#xff0c;在此分享多项式回归这一回归算法原理。本章的回归算法原理基于《基于广告费预测点击量》项目&#xff0c;…

Adaboost集成学习 | Matlab实现基于LSTM-Adaboost长短期记忆神经网络结合Adaboost集成学习多输入单输出时间序列预测

目录 效果一览基本介绍模型设计程序设计参考资料效果一览 基本介绍 Adaboost集成学习 | Matlab实现基于LSTM-Adaboost长短期记忆神经网络结合Adaboost集成学习时间序列预测(股票价格预测) 模型设计 步骤1: 数据准备 收集和整理历史数据。确保数据集经过适当的预处理,如归一…

【人工智能】Transformers之Pipeline(五):深度估计(depth-estimation)

目录 一、引言 二、深度估计&#xff08;depth-estimation&#xff09; 2.1 概述 2.2 技术路径 2.3 应用场景 2.4 pipeline参数 2.4.1 pipeline对象实例化参数 2.4.2 pipeline对象使用参数 2.4 pipeline实战 2.5 模型排名 三、总结 一、引言 pipeline&#xff08…

mysql JSON特性优化

有朋友问到&#xff0c;mysql如果要根据json中的某个属性过滤&#xff0c;数据量大的话&#xff0c;性能很差&#xff0c;要如何提高性能&#xff1f; 为什么要用json串&#xff1f; 由于一些特定场景&#xff0c;mysql需要用到json串&#xff0c;例如文档&#xff0c;不同的…