当前位置: 首页 > 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…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...