当前位置: 首页 > news >正文

数据结构(Java版)第七期:LinkedList与链表(二)

专栏:数据结构(Java版)

个人主页:手握风云

一、链表的实现(补)

        接上一期,下面我们要实现删除所有值为key的元素,这时候有的老铁就会想用我们上一期中讲到的remove方法,循环使用remove方法,去删除完值为key的元素。如下图所示,比如我们要删除值为22的节点,使用remove方法循环,此时这个算法的时间复杂度就会为O(n^{2}),算法效率就会比较低。那我们能不能只让cur遍历一遍这个链表,就删除所有值为22的节点呢?

    @Overridepublic void removeAllKey(int key) {ListNode cur = head.next;ListNode prev = head;if(head == null){return;}while(cur != null){if(cur.val == key){prev.next = cur.next;}else{prev = cur;}cur = cur.next;}}

       这样我们就可以实现删除所有职位key的元素,但我们要思考一下,这段代码的问题。我们来运行测试一下。

public class Main {public static void main(String[] args) {IList mySingleList = new MySingleList();mySingleList.addLast(22);mySingleList.addLast(22);mySingleList.addLast(22);mySingleList.addLast(33);mySingleList.display();mySingleList.removeAllKey(22);mySingleList.display();}
}

     我们就会发现运行结果里面还有22。如下图所示,我们会看到,当cur走到第三个节点时,第二个22就会变成新的头,走得时候又会把新的22给忽略掉。我们可以这样解决这个问题。

    @Overridepublic void removeAllKey(int key) {ListNode cur = head.next;ListNode prev = head;if(head == null){return;}while(head.val == key){head = head.next;}while(cur != null){if(cur.val == key){prev.next = cur.next;}else{prev = cur;}cur = cur.next;}}

二、链表中经典的面试题

2.1. 反转链表

    反转链表是将链表的结构进行反转,同时包括数据与地址。过程如下图所示。

       对于这道题,我们可以采用头插的思想来解决。我们需要定义两个变量cur和curNext,利用以下代码来解决。我们先把head.next置为空,把cur方法到第二个节点上,然后把第二个节点采用头插的方法进行插入。可我们把cur改了之后,就会找不到下一个节点了,我们再定义一个curNext

while(cur != null){curNext = cur.next;cur.next = head;head = cur;cur = curNext;
}

2.2. 链表的中间结点

        第一种方法,可以先求出链表长度,再定义一个引用,走到len/2的位置。但这种方法需要先定义cur节点去遍历一边数组得出链表的长度,再定义一个len变量走到中间节点的位置,这样就会需要遍历两遍链表。那我们能不能只遍历一遍数组得出中间节点。

       类比一下,试想两个人赛跑,其中一人是另一个人速度的两倍,当速度快的到达终点时,速度慢的刚到达中点。同样,我们定义一个fast和slow两个引用变量。fast一次走两步,slow一次走一步。如果链表有奇数个结点时,当fast.next==null时,slow指向中间结点;如果链表有偶数个结点时,当fast==null时,slow指向中间结点。

public class Solution {static class ListNode{private int val;private Solution.ListNode next;public ListNode(Solution.ListNode next) {this.next = next;}public ListNode(int val, Solution.ListNode next) {this.val = val;this.next = next;}}public ListNode middleNode(ListNode head){if(head == null){return null;}ListNode fast = head;ListNode slow = head;while(fast != null && fast.next != null){
//这里不能是||,因为||无法到达链表的尾部
//两个条件的顺序不能互换,因为fast为空,fast.next就会空指针异常fast = fast.next.next;slow = slow.next;}return slow;}public static void main(String[] args) {ListNode node5 = new ListNode(5,null);ListNode node4 = new ListNode(4,node5);ListNode node3 = new ListNode(3,node4);ListNode node2 = new ListNode(2,node3);ListNode node1 = new ListNode(1,node2);Solution solution = new Solution();ListNode middleNode = solution.middleNode(node1);System.out.println(middleNode.val);}
}

2.3. 返回倒数第k个结点

        我们依然可以参照上面的双引用的例子,先让slow不动,fast引用先走k-1步。然后两个引用在同时走。当fast走到最后的时候,slow就能走到倒数第k个结点。 

public class Solution {static class ListNode{int val;ListNode next;public ListNode(){}public ListNode(int val) {this.val = val;}public ListNode(int val, ListNode next) {this.val = val;this.next = next;}}public int kthToLast(ListNode head, int k){ListNode fast = head;ListNode slow = head;int count = 0;while(count != k-1){fast = fast.next;count++;}while(fast.next != null){fast = fast.next;slow = slow.next;}return slow.val;}
}

       这样的代码还不是特别严谨的。加入我们输入了5个结点,要求我们返回第6个结点,那我们的fast就需要走5步,直接指向了空指针,我们可以再写一个if语句来返回-1。或者是我们可以写成异常来接收,但在OJ测试上,异常不会通过。

if(fast == null){return -1;
}

     以下为完整代码:

import java.util.Scanner;public class Solution {static class ListNode{int val;ListNode next;public ListNode(){}public ListNode(int val) {this.val = val;}public ListNode(int val, ListNode next) {this.val = val;this.next = next;}}public int kthToLast(ListNode head, int k){ListNode fast = head;ListNode slow = head;int count = 0;while(count != k-1){fast = fast.next;if(fast == null){return -1;}count++;}while(fast.next != null){fast = fast.next;slow = slow.next;}return slow.val;}public static void main(String[] args) {Scanner in = new Scanner(System.in);ListNode node5 = new ListNode(5,null);ListNode node4 = new ListNode(4,node5);ListNode node3 = new ListNode(3,node4);ListNode node2 = new ListNode(2,node3);ListNode node1 = new ListNode(1,node2);int k = in.nextInt();Solution solution = new Solution();int result = solution.kthToLast(node1,k);System.out.println(result);}
}

2.4. 合并两个有序链表

       两个链表合并之后,要满足升序的条件,就需要对两个链表所指向的结点值进行比较,这就需要两个引用都不能为空。我们先定义一个傀儡结点newH,如上图所示,起初headA的val值比headB的val值小,那么headA就会指向下一个结点,再把0x23赋给我们的傀儡结点,再与headB的val值进行比较。那我们就可以写一个循环来对val进行比较。

       我们还需要再定义一个ListNode.tmp,当headA走到下一个结点时,tmp走到上一个结点,这样就能保证刚进行比较的两个结点中最小的结点值是新创建链表的最后一个结点。

while(headA != null && headB != null){if(headA.val < headB.val){tmp.next = headA;headA = headA.next;tmp = tmp.next;} else {tmp.next = headB;headB = headB.next;tmp = tmp.next;}
}

      在这个循环当中,一定会出现一种情况,其中一个链表先走完,而另一个链表还没有走完,此时先走完的链表已经指向空引用了,while循环就会跳出。我们利用下面的伪代码来遍历未完成的结点。

if(headA != null){tmp.next = headA;
} else {tmp.next = headB;
}

以下为完整代码:

public class Solution {static class ListNode{int val;ListNode next;public ListNode(){}public ListNode(int val) {this.val = val;}public ListNode(int val, ListNode next) {this.val = val;this.next = next;}}public ListNode mergeTwoLists(ListNode list1, ListNode list2){ListNode newH = new ListNode(-1);ListNode tmp = newH;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 = list1;} else {tmp.next = list2;}return newH.next;}public static void main(String[] args) {ListNode list1 = new ListNode(1);list1.next = new ListNode(2);list1.next.next = new ListNode(4);ListNode list2 = new ListNode(0);list2.next = new ListNode(3);list2.next.next = new ListNode(4);Solution solution = new Solution();ListNode mergedList = solution.mergeTwoLists(list1,list2);while (mergedList != null) {System.out.print(mergedList.val + " ");mergedList = mergedList.next;}}
}

相关文章:

数据结构(Java版)第七期:LinkedList与链表(二)

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 一、链表的实现&#xff08;补&#xff09; 接上一期&#xff0c;下面我们要实现删除所有值为key的元素&#xff0c;这时候有的老铁就会想用我们上一期中讲到的remove方法&#xff0c;循环使用remove方法&#…...

ant-design-vue 1.X 通过id获取a-input组件失败

1.ant-design-vue 1.X 问题描述 当我在a-form组件中&#xff0c;以v-decorator指令绑定表单组件时&#xff0c;无法根据我设置的verify-code-input获取元素 <a-input type"text" id"verify-code-input" class"paIpt":placeholder"$t(…...

Flutter:吸顶效果

在分页中&#xff0c;实现tab吸顶。 TDNavBar的screenAdaptation: true, 开启屏幕适配。 该属性已自动对不同手机状态栏高度进行适配。我们只需关注如何实现吸顶。 view import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import p…...

MATLAB语言的数据类型

MATLAB语言的数据类型详解 MATLAB&#xff08;矩阵实验室&#xff09;是一种广泛应用于科学计算、数据分析、算法开发及模型构建的高性能语言和环境。MATLAB的强大之处不仅在于其丰富的数学工具和可视化功能&#xff0c;还有其灵活多变的数据类型。这篇文章将详细介绍MATLAB中…...

priority_queue优先队列

目录 1. 最短路径算法&#xff08;Dijkstra算法&#xff09; 应用场景&#xff1a; 优先队列的作用&#xff1a; 2. 最小生成树算法&#xff08;Prim算法&#xff09; 应用场景&#xff1a; 优先队列的作用&#xff1a; 3. 哈夫曼编码&#xff08;Huffman Coding&#x…...

HarmonyOS 鸿蒙Next 预览pdf文件

HarmonyOS 鸿蒙Next 预览pdf文件 1、使用filePreview 2、使用web组件 在线pdf&#xff08;网址是直接下载的&#xff0c;不是直接可以预览的&#xff09;&#xff0c;先下载再预览 import media from ohos.multimedia.media;import web_webview from ohos.web.webview;import …...

vscode开启调试模式,结合Delve调试器调试golang项目详细步骤

1.前期准备 (1).在vs code中的扩展程序中搜索并安装Go扩展程序 (2).安装 Delve 调试器 go install github.com/go-delve/delve/cmd/dlvlatest (3).打开vs code的命令面板&#xff0c;输入Go: Install/Update Tools&#xff0c;并单击该命令执行&#xff0c;安装或更新Go语…...

身份鉴权(PHP)(小迪网络安全笔记~

免责声明&#xff1a;本文章仅用于交流学习&#xff0c;因文章内容而产生的任何违法&未授权行为&#xff0c;与文章作者无关&#xff01;&#xff01;&#xff01; 附&#xff1a;完整笔记目录~ ps&#xff1a;本人小白&#xff0c;笔记均在个人理解基础上整理&#xff0c;…...

【git】-初始git

一、什么是版本控制&#xff1f; 二、Git的安装 三、掌握Linux常用命令 四、Git基本操作 1、提交代码 2、查看历史提交 3、版本回退 一、什么是版本控制&#xff1f; 版本控制是一种用于记录文件或项目内容变化的系统。它通过版本标识和版本历史记录来管理不同版本&#…...

CSS 盒模型

盒模型 CSS盒模型是网页布局的核心概念之一&#xff0c;它描述了网页元素的物理结构和元素内容与周围元素之间的关系。根据W3C规范&#xff0c;每个HTML元素都被视为一个矩形盒子&#xff0c;这个盒子由以下四个部分组成&#xff1a; 内容区&#xff08;Content area&#xff…...

[0405].第05节:搭建Redis主从架构

Redis学习大纲 一、3主3从的集群配置&#xff1a; 1.1.集群规划 1.分片集群需要的节点数量较多&#xff0c;这里我们搭建一个最小的分片集群&#xff0c;包含3个master节点&#xff0c;每个master包含一个slave节点&#xff0c;结构如下&#xff1a; 2.每组是一主一从&#x…...

6 分布式限流框架

限流的作用 在API对外互联网开放的情况下&#xff0c;是无法控制调用方的行为的。当遇到请求激增或者黑客攻击的情况下&#xff0c;会导致接口占用大量的服务器资源&#xff0c;使得接口响应效率的降低或者超时&#xff0c;更或者导致服务器宕机。 限流是指对应用服务进行限制…...

sosadmin相关命令

sosadmin命令 以下是本人翻译的官方文档&#xff0c;如有不对&#xff0c;还请指出&#xff0c;引用请标明出处。 原本有个对应表可以跳转的&#xff0c;但是CSDN的这个[](#)跳转好像不太一样&#xff0c;必须得用html标签&#xff0c;就懒得改了。 sosadmin help 用法 sosadm…...

关于大数据的基础知识(四)——大数据的意义与趋势

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于大数据的基础知识&#xff08;四&a…...

【EI,Scopus检索 | 往届均已检索见刊】第四届智能系统、通信与计算机网络国际学术会议(ISCCN 2025)

重要信息&#xff1a; 大会官网&#xff1a;更多详情【论文投稿】 截稿时间&#xff1a;以官网信息为准 大会时间&#xff1a;2025年2月21-23日 接受/拒稿通知&#xff1a;投稿后3-5个工作日内 收录检索&#xff1a;EI&#xff0c;Scopus 出版信息&#xff1a; 本会议所有…...

smplx blender插件笔记

目录 liunx安装&#xff1a; liunx安装&#xff1a; pip install smplx 这个创建模型报错 SMPL_blender_addon...

【算法】移除元素

今天讲的是力扣题目的题解&#xff1a; 力扣题目&#xff1a; 72.移除元素 题目描述&#xff1a; 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不…...

【后端面试总结】设计一个分布式锁需要考虑哪些东西

分布式锁是我们在分布式场景中经常用到的一种技术&#xff0c;在后端面试中也是出镜率很高&#xff0c;那么我们设计分布式锁的时候应该从那几方面去考虑呢 实现分布式锁需要考虑的点 设置超时时间 设置超时时间的目的是为了避免这个场景&#xff1a;进程A拿了锁&#xff0c…...

awr报告无法生成:常见案例与解决办法

awr报告无法生成:常见案例与解决办法 STATISTICS_LEVEL设置过低数据库打开状态不对主库隐含参数设置错误MMON子进程被SuspendSYS模式统计信息过期WRH$_SQL_PLAN表数据量太大AWR绑定变量信息收集超时撞上数据库Bug 9040676STATISTICS_LEVEL设置过低 STATISTICS_LEVEL设置为BAS…...

Hadoop 生态之 kerberos

参考链接 https://winway.github.io/2022/04/02/kerberos-ranger/ https://ieevee.com/tech/2016/06/22/ranger-2.html kerberos解决”who are you“的问题 ranger解决”what you can do“的问题 LDAP 轻型目录访问协议&#xff08;英文&#xff1a;Lightweight Director…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL

ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...

WebRTC调研

WebRTC是什么&#xff0c;为什么&#xff0c;如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...