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

数据结构入门到入土——链表(1)

目录

一,顺序表表/ArrayList的缺陷

二,链表

三,链表的实现

四,与链表有关的题目练习(1)

1.删除链表中等于给定值 val 的所有节点

2.反转一个单链表

3.给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点

4.输入一个链表,输出该链表中倒数第k个结点

5.将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的

6.编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前

7.链表的回文结构


一,顺序表表/ArrayList的缺陷

在上期我们已经熟悉了ArrayList的使用,并且进行了简单模拟实现。通过源码我们知道ArrayList底层使用数组来存储元素。

由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后 搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。因此:java集合中又引入了LinkedList,即 链表结构

二,链表

如果说顺序表其底层在物理意义上是一段连续的空间,那么链表便是是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。

顺序表是一段连续不可分的空间:

链表像一列火车一样,多个节点被串成一块具有连续性意义的结构,实际上各个节点都来自于不同的地址:

实际中链表的结构非常多样
单向或者双向:
有头或者没头:
循环或者非循环:
虽然有这么多的链表的结构,但是我们重点掌握两种:
•    无头单向非循环链表 结构简单 ,一般不会单独用来存数据。实际中更多是作为 其他数据结构的子结构 ,如哈希桶、图的邻接表等等。
•    无头双向链表 :在 Java 的集合框架库中 LinkedList 底层实现就是无头双向循环链表。

三,链表的实现

和上期顺序表一样,我们采用接口的方式实现:

接口部分:

// 1、无头单向非循环链表实现
public interface IList {//头插法public void addFirst(int data);//尾插法public void addLast(int data);//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data);//查找是否包含关键字key是否在单链表当中public boolean contains(int key);//删除第一次出现关键字为key的节点public void remove(int key);//删除所有值为key的节点public void removeAllKey(int key);//得到单链表的长度public int size();//清空链表public void clear();//打印链表public void display();
}

接口方法实现:

public class AchieveList implements IList{static class ListNode {public int val;public ListNode next;public ListNode(int val) {this.val = val;}}public ListNode head;//创建一个链表public void crateList() {ListNode node1 = new ListNode(12);ListNode node2 = new ListNode(34);ListNode node3 = new ListNode(56);ListNode node4 = new ListNode(78);ListNode node5 = new ListNode(99);node1.next = node2;node2.next = node3;node3.next = node4;node4.next = node5;this.head = node1;}//头插法@Overridepublic void addFirst(int data) {ListNode node =new ListNode(data);node.next = this.head;this.head = node;}//尾插法@Overridepublic void addLast(int data) {ListNode cur = this.head;while (cur.next != null) {cur = cur.next;}ListNode node = new ListNode(data);cur.next = node;}//任意位置插入,第一个数据节点为0号下标@Overridepublic void addIndex(int index, int data) {ListNode node = new ListNode(data);ListNode cur = this.head;ListNode prev = this.head;if (index == 0) {node.next = cur;this.head = node;} else {int count = 0;while (count != index) {cur = cur.next;count++;}count = 0;while ((count+1) != index) {prev = prev.next;count++;}node.next = cur;prev.next = node;}}//查找是否包含关键字key是否在单链表当中@Overridepublic boolean contains(int key) {ListNode cur = this.head;while (cur != null) {if (cur.val == key) {return true;}cur = cur.next;}return false;}//删除第一次出现关键字为key的节点@Overridepublic void remove(int key) {if (head == null) {return;}ListNode cur = this.head;ListNode prev = this.head;int count = 1;while (cur.val != key) {if (count == size()) {return;}cur = cur.next;count++;}if (count == 1) {head = null;head = prev.next;} else {while (prev.next.val != key) {prev = prev.next;}prev.next = cur.next;}}//删除所有值为key的节点@Overridepublic void removeAllKey(int key) {ListNode cur = this.head;int count = 1;while (cur.next != null) {if (cur.val == key) {count++;}cur = cur.next;}for (int i = 0; i < count; i++) {remove(key);}}//得到单链表的长度@Overridepublic int size() {int count = 1;ListNode cur = this.head;if (cur == null) {return 0;}while (cur.next != null) {cur = cur.next;count++;}return count;}@Overridepublic void clear() {ListNode cur = this.head;while (cur.next != null) {head = null;head = cur.next;cur = cur.next;}head = null;}//打印链表@Overridepublic void display() {ListNode cur = this.head;if (head == null) {System.out.println("[" + "]");} else {System.out.print("[");while (cur != null) {if (cur.next == null) {System.out.println(cur.val + "]");} else {System.out.print(cur.val + " ");}cur = cur.next;}}}

四,与链表有关的题目练习(1)

1.删除链表中等于给定值 val 的所有节点

class Solution {public ListNode removeElements(ListNode head,int val) {if (head == null) {return null;}ListNode cur = head.next;ListNode prev = head;while (cur != null) {if (cur.val == val) {prev.next = cur.next;cur = cur.next;} else {cur = cur.next;prev = prev.next;}}if (head.val == val) {head = head.next;}return head;}}

2.反转一个单链表

思路:

现有如下链表:

定义cur = head.next

将head.next指向null

定义变量curNext = cur.next

将cur的下一个节点设为head

令cur = curNext;curNext = cur.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;}}

3.给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点

思路:

定义如图两个变量fast和slow,且都等于head

令fast每次走两步,slow每次走一步。当fast==null或者fast.next === null时

此时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个结点

假设有以下链表:

要求倒数第k个节点,我们可以先定义fast和slow两个位于头节点的变量

假如K为3,我们就先令fast先走K-1步

然后令fast和slow一起走同样的步数,直到fast.next为null

此时slow对应的位置就是所求的倒数第K个节点

public class Solution {public ListNode FindKthToTail(ListNode head,int k) {if (head == null) {return head;}if (k <= 0 && head != null ) {return null;}ListNode fast = head;ListNode slow = head;for (int i = 0; i < k-1; i++) {fast = fast.next;//处理K太大的问题if (fast == null) {return null;}}while (fast.next != null) {fast = fast.next;slow = slow.next;}return slow;}}

5.将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的

思路:

先有以下两个有序链表需要被合并为一个有序链表

定义一个newH节点

将head1.val与head2.val进行比较,较小令它等于tmpH且令它等于它的下一个节点,tmpH为newH的下一个节点

如上图head1.val<head2.val,故发生以下变化

接着对head1.val与head2.val进行比较

head2.val更小

继续比较

head1.val更小

继续比较

head2.val更小

……

当其中有一个数组比较完了的时候,此时只需令tmpH.next为另一个head即可

最后返回newH.next即可

class Solution {public ListNode mergeTwoLists(ListNode head1, ListNode head2) {ListNode newH = new ListNode(-1);ListNode tmpH = newH;while (head1 != null && head2 != null) {if (head1.val < head2.val) {tmpH.next = head1;tmpH = tmpH.next;head1 = head1.next;} else {tmpH.next = head2;tmpH = tmpH.next;head2 = head2.next;}}if (head1 != null) {tmpH.next = head1;}if (head2 != null) {tmpH.next = head2;}return newH.next;}}

6.编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前

使用cur遍历顺序表

当cur.val<给定的值x时就让它进入链表1

当cur.val>=给定的值x时就让它进入链表2

最后将链表2的尾部插在链表1的头部,返回链表2

public class Partition {public ListNode partition(ListNode pHead, int x) {ListNode cur = pHead;ListNode tmpH1 = new ListNode(-1);ListNode tmpH2 = new ListNode(-1);ListNode head1 = tmpH1;ListNode head2 = tmpH2;while (cur != null) {if (cur.val < x) {head2.next = cur;head2 = head2.next;} else {head1.next = cur;head1 = head1.next;}cur = cur.next;}tmpH2 = tmpH2.next;tmpH1 = tmpH1.next;head2.next = tmpH1;head1.next = null;if (tmpH2 == null) {return tmpH1;}if (tmpH1 == null) {return tmpH2;}return tmpH2;}}

7.链表的回文结构

通过以上快慢指针的方式找到链表的中间节点

翻转

当slow和fast相遇时停止

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 curNext = cur.next;cur.next = slow;slow = cur;cur = curNext;}ListNode right = slow;ListNode left = A;//从前到后  从后到前while (left.next != right.next ) {if (left.val != right.val) {return false;}if (left.next == right){return true;}left = left.next;right = right.next;}return true;}}

相关文章:

数据结构入门到入土——链表(1)

目录 一&#xff0c;顺序表表/ArrayList的缺陷 二&#xff0c;链表 三&#xff0c;链表的实现 四&#xff0c;与链表有关的题目练习&#xff08;1&#xff09; 1.删除链表中等于给定值 val 的所有节点 2.反转一个单链表 3.给定一个带有头结点 head 的非空单链表&#xf…...

MySQL C API的使用

MySQL C API的使用 介绍及使用 MySQL C API&#xff08;也称为 MySQL Connector/C&#xff09;是用于与 MySQL 数据库交互的 C 语言 API。它提供了一组函数和结构体&#xff0c;允许你在 C 程序中连接到 MySQL 数据库服务器&#xff0c;并执行查询、插入、更新等数据库操作。…...

JavaScript防御性编程

简单聊一下防御性编程&#xff0c;初衷是开发人员为了防止自己被裁员&#xff0c;而将代码编写为只有自己能看懂。如何只有自己能看懂&#xff1f;方法多种多样&#xff0c;但不能将简单问题复杂化&#xff0c;比如&#xff1a;编写一堆无效的逻辑关系&#xff0c;或将业务复杂…...

微信预约小程序制作指南:从小白到专家

在当今的数字时代&#xff0c;微信小程序已经成为了一种非常流行的应用方式。预约功能更是成为了许多小程序的核心功能之一。如果你也想为你的小程序添加预约功能&#xff0c;以下步骤将会对你有所帮助。 一、进入乔拓云网后台 乔拓云网是一个在线小程序开发平台&#xff0c;你…...

向量数据库:Milvus

特性 Milvus由Go(63.4%),Python(17.0%),C(16.6%),Shell(1.3%)等语言开发开发&#xff0c;支持python&#xff0c;go&#xff0c;java接口(C,Rust,c#等语言还在开发中)&#xff0c;支持单机、集群部署&#xff0c;支持CPU、GPU运算。Milvus 中的所有搜索和查询操作都在内存中执行…...

亚马逊国际商品详情 API:获取特定商品详细信息的实践

随着电子商务的飞速发展&#xff0c;亚马逊作为全球最大的在线零售商之一&#xff0c;提供了丰富的商品详情 API&#xff0c;使得第三方开发者能够轻松地获取亚马逊网站上的商品信息。本文将介绍如何使用亚马逊国际商品详情 API&#xff08;Amazon Product Advertising API&…...

MSB30M-ASEMI小贴片整流桥MSB30M

编辑&#xff1a;ll MSB30M-ASEMI小贴片整流桥MSB30M 型号&#xff1a;MSB30M 品牌&#xff1a;ASEMI 封装&#xff1a;UMSB-4 最大平均正向电流&#xff1a;3A 最大重复峰值反向电压&#xff1a;1000V 产品引线数量&#xff1a;4 产品内部芯片个数&#xff1a;4 产品…...

Redis启动方式

redis三种启动方式 1.直接启动 进入redis根目录&#xff0c;执行命令: #加上‘&’号使redis以后台程序方式运行 ./redis-server & 2.通过指定配置文件启动 可以为redis服务启动指定配置文件&#xff0c;例如配置为/etc/redis/6379.conf 进入redis根目录&#x…...

TEMU 新手小白必看!2024入驻流程/入驻类目/入驻资料等详细流程讲解

2023 TEMU 可谓是赚足眼球&#xff0c;流量持续上涨&#xff0c;2024年相信不少卖家们已经跃跃欲试&#xff0c;但大陆卖家如何入驻TEMU&#xff1f;哪些品类适合入驻&#xff1f;又有哪些入驻要求和资料&#xff1f;别急&#xff0c;今天东哥就一一给大家详细讲解&#xff0c;…...

【C语言】数组

一维数组的创建和初始化 数组是一组相同类型元素的集合。 数组的创建 //数组的创建方式&#xff1a;type_t arr_name [const_n];//type_t 是指数组的元素类型//const_n 是一个常量表达式&#xff0c;用来指定数组的大小数组创建的实例&#xff1a; 数组创建&#xff…...

常见测试技术都有哪些?

测试技术是用于评估系统或组件的方法&#xff0c;目的是发现它是否满足给定的要求。系统测试有助于识别缺口、错误&#xff0c;或与实际需求不同的任何类型的缺失需求。测试技术是测试团队根据给定的需求评估已开发软件所使用的最佳实践。这些技术可以确保产品或软件的整体质量…...

Spring事务控制

1.事务介绍 1.1什么是事务&#xff1f; 当你需要一次执行多条SQL语句时&#xff0c;可以使用事务。通俗一点说&#xff0c;如果这几条SQL语句全部执行成功&#xff0c;则才对数据库进行一次更新&#xff0c;如果有一条SQL语句执行失败&#xff0c;则这几条SQL语句全部不进行执…...

swaggerUI不好用,试试这个openapiUI?

title: swaggerUI不好用&#xff0c;试试这个openapiUI? date: 2024-01-08 categories: [tool] tags: [openapi,工具] description: 基于swaggger2, openapi3规范的UI文档 1.背景 由于长期使用 swaggerUI 工具&#xff0c;它的轻量风格个人觉得还是不错的&#xff0c;但是它…...

嵌入式物联网项目开发实战例程-STM32F103系列之外围器件代码

开发STM32F103很好的参考例程&#xff0c;轻松实现各类外围器件的开发。持续更新中&#xff0c;欢迎关注及收藏。 0001基于STM32F103单片机GPIO实现控制LED灯闪烁的程序代码.zip 0002基于STM32F103单片机GPIO实现按键KEY的检测程序代码.zip 0003基于STM32F103单片机GPIO实现外部…...

Docker Compose--部署SpringBoot项目--实战

原文网址&#xff1a;Docker Compose--部署SpringBoot项目--实战-CSDN博客 简介 本文用实战介绍Docker Compose部署SpringBoot项目。 ----------------------------------------------------------------------------------------------- 分享Java真实高频面试题&#xff0c…...

单电阻FOC算法实现永磁同步电机的调整步骤和设置

本文档介绍了使用 单电阻FOC 算法实现永磁同步电机&#xff08;Permanent Magnet Synchronous Motor&#xff0c;PMSM&#xff09;调整所需的步骤和设置。由于不同电机存在参数差异&#xff0c;因此需针对不同的电机和负载对该算法进行调整。该电机库已经在在落地扇和空净等风机…...

化学DS-1040 Tosylate 抑制剂 1335138-89-0科研用途

化合物1219962-49-8是一种小分子化合物&#xff0c;分子式为C15H25N3O4&#xff0c;相对分子质量为305.37。该化合物为白色至灰白色粉末&#xff0c;不溶于水&#xff0c;易溶于有机溶剂&#xff0c;如甲醇、乙醇等。 AT791是一种与细胞周期调控相关的蛋白激酶&#xff0c;参与…...

PaddlePaddle初使用

模型导出与预测 # -c 后面设置训练算法的yml配置文件 # -o 配置可选参数 # Global.pretrained_model 参数设置待转换的训练模型地址&#xff0c;不用添加文件后缀 .pdmodel&#xff0c;.pdopt或.pdparams。 # Global.save_inference_dir参数设置转换的模型将保存的地址。pytho…...

【FPGA】分享一些FPGA数字信号处理相关的书籍

在做FPGA工程师的这些年&#xff0c;买过好多书&#xff0c;也看过好多书&#xff0c;分享一下。 后续会慢慢的补充书评。 【FPGA】分享一些FPGA入门学习的书籍【FPGA】分享一些FPGA协同MATLAB开发的书籍 【FPGA】分享一些FPGA视频图像处理相关的书籍 【FPGA】分享一些FPGA高速…...

深度解析JavaScript面试热点:事件循环、上下文、箭头函数、变量作用域与ES6模块

JavaScript面试中经常涉及到事件循环、上下文、箭头函数、变量作用域以及ES6模块等核心概念。通过清晰的代码示例&#xff0c;我们深入讨论这些主题&#xff0c;揭示其中的关键细节。 事件循环&#xff08;Event Loop&#xff09; JavaScript开发者每天都与事件循环打交道&am…...

Javaweb之Mybatis的动态SQL的详细解析

3. Mybatis动态SQL 3.1 什么是动态SQL 在页面原型中&#xff0c;列表上方的条件是动态的&#xff0c;是可以不传递的&#xff0c;也可以只传递其中的1个或者2个或者全部。 而在我们刚才编写的SQL语句中&#xff0c;我们会看到&#xff0c;我们将三个条件直接写死了。 如果页面…...

物联网与智能家居:跨境电商与未来生活的融合

物联网&#xff08;Internet of Things&#xff0c;IoT&#xff09;和智能家居技术正迅速崛起&#xff0c;成为跨境电商领域的创新引擎。这两者的巧妙结合不仅为消费者提供更智能、便捷的生活方式&#xff0c;同时也为电商平台和制造商带来了全新的商机。本文将深入探讨物联网与…...

Java内存模型(JMM)是基于多线程的吗

Java内存模型&#xff08;JMM&#xff09;是基于多线程的吗 这个问题按我的思路转换了下&#xff0c;其实就是在问&#xff1a;为什么需要Java内存模型 总结起来可以由几个角度来看待「可见性」、「有序性」和「原子性」 面试官&#xff1a;今天想跟你聊聊Java内存模型&#…...

Linux离线安装MySQL(rpm)

目录 下载安装包安装MySQL检测安装结果服务启停MySQL用户设置 下载安装包 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 下载全量包如&#xff1a;(mysql-8.1.0-1.el7.x86_64.rpm-bundle.tar) 解压&#xff1a;tar -xzvf mysql-8.1.0-1.el7.x86_64.…...

用 Socket.D 替代原生 WebSocket 做前端开发

socket.d.js 是基于 websocket 包装的 socket.d 协议的实现。就是用 ws 传输数据&#xff0c;但功能更强大。 功能原生 websocketsocket.d说明listen有有监听消息send有有发消息sendAndRequest无有发消息并接收一个响应&#xff08;类似于 http&#xff09;sendAndSubscribe无…...

Transformer架构和对照代码详解

1、英文架构图 下面图中展示了Transformer的英文架构&#xff0c;英文架构中的模块名称和具体代码一一对应&#xff0c;方便大家对照代码、理解和使用。 2、编码器 2.1 编码器介绍 从宏观⻆度来看&#xff0c;Transformer的编码器是由多个相同的层叠加⽽ 成的&#xff0c;每个…...

大数的乘法

题目描述 求两个不超过100位的非负整数的乘积。 输入 有两行&#xff0c;每行是一个不超过100位的非负整数&#xff0c;没有多余的前导0。 输出 一行&#xff0c;相乘后的结果。 样例输入 Copy 123456789 123456789样例输出 Copy 15241578750190521 代码实现&#xff1…...

年度征文 | 机器学习之心的2023

机器学习之心的2023 2023是极其复杂的一年。 生活上&#xff0c;养了很多宠物。 工作上&#xff0c;写了不少博客。 虽然遇见更多让人不开心的事情&#xff0c;但总体还是美好的。 愿大家新的一年健康平安&#xff0c;生活幸福&#xff01; 机器学习是一项庞大的工程&#xff0…...

13.Kubernetes应用部署完整流程:从Dockerfile到Ingress发布完整流程

本文以一个简单的Go应用Demo来演示Kubernetes应用部署的完整流程 1、Dockerfile多阶段构建 Dockerfile多阶段构建 [root@docker github]# git clone https://gitee.com/yxydde/http-dump.git [root@docker github]# cd http-dump/ [root@docker http-dump]# cat Dockerfile …...

多年后再用TB,谈项目管理工具

背景 最近启动一个小项目&#xff0c;多年未曾使用项目管理工具&#xff0c;依稀记得使用过Basecamp,Tower,worktitle,teambition等等&#xff0c;当然还有mantis&#xff0c;vs project等等。于是随便翻阅找个用&#xff0c;不小心翻了TB的牌子&#xff0c;竟然已是阿里旗下的…...

天猫网站左侧导航用js怎么做/seo推广怎么样

方法有点笨&#xff0c;但是&#xff0c;没有找到好一点的办法&#xff0c;就这样先装着&#xff0c;看朋友们是否也有需要&#xff0c;记录一下 CentOS 下安装MySQL5.7的时候出现各种问题&#xff0c;各种报错&#xff0c;试过无数办法&#xff0c;今天终于安装上去&#xff0…...

dwcs5怎么做动态网站后台/google网站增加关键词

PicConvert for mac是一款全新的图像格式转换工具&#xff0c;picconvert mac版支持批量转换和调整图像大小&#xff0c;快速帮助用户将图像转换成需要的格式&#xff0c;比如jpg、png、tiff、heic、jpx、bmp等&#xff0c;使用非常便捷&#xff0c;如果你想要转换图片的格式&a…...

wordpress订阅会员/谷歌独立站

采用phpsmary来模拟dedecms后台?>"更新所有文档”的功能。特别说明&#xff0c;因为是在本机测试&#xff0c;只是为了能看到实现的功能&#xff0c;所以写得很简单。当然&#xff0c;本人也是菜鸟级php爱好者&#xff0c;欢迎大家批评指正。第一步&#xff1a;下载和…...

北京 网站定制开发/自媒体怎么赚钱

Kubernetes是谷歌开源的容器集群编排平台&#xff0c;是一个完备的分布式系统支撑平台&#xff0c;为容器化应用提供部署运行、资源调度、服务发现和动态伸缩等一系列完整功能&#xff0c;具有强大的故障发现和自我修复机制、服务滚动升级和在线扩容能力&#xff0c;可扩展资源…...

做网站容易找工作吗/关键词工具有哪些

我们都做过一道题&#xff08;&#xff1f;&#xff09;货币兑换&#xff0c;是用cdq分治来解决不单调的斜率优化 现在它放到了树上.. 总之先写下来dp方程&#xff0c;$f[i]min\{f[j](dis[i]-dis[j])*p[i]q[i]\} ,j是i的祖先,dis[i]-dis[j]<l[i]$ &#xff0c;其中dis[i]表示…...

网站设计做微信发现界面/企业品牌推广方案

具体代码如下所述&#xff1a; srpgame.py #!/urs/bin/env python import random all_choice [石头,剪刀,布] win_list [[石头,剪刀],[剪刀,布],[布,石头]] prompt """ (0) 石头 (1) 剪刀 (2) 布 Please input your choice(0/1/2): """ compu…...