链表知识回顾

类型:单链表,双链表、循环链表

存储:在内存中不是连续存储

删除操作:即让c的指针指向e即可,无需释放d,因为java中又内存回收机制

添加节点: 

链表的构造函数

public 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;}
}

可以直接用java自带的LinkedList类实现链表的初始化

import java.util.LinkedList;public class Main {public static void main(String[] args) {// 创建一个空的链表LinkedList<Integer> list = new LinkedList<>();// 向链表中添加元素list.add(1);list.add(2);list.add(3);// 打印链表内容System.out.println(list);}
}

链表的声明:

Java标准库提供了LinkedList类,位于java.util包中。它的特点如下:

  • 实现细节LinkedList底层通常实现为双向链表,这意味着每个节点除了指向下一个节点,还保存对前一个节点的引用。
  • 接口实现:除了实现List接口外,LinkedList还实现了Deque接口,使其既可以当作列表使用,也可以当作队列(或双端队列)使用。
  • 增删操作add(), remove(), offer(), poll()等方法在链表头尾插入或删除元素时性能较高。
  • 遍历操作:由于链表没有下标索引,随机访问通常较慢。如果频繁使用随机访问,可以考虑使用ArrayList,ArrayList 底层是基于动态数组实现的
LinkedList<Integer> list = new LinkedList<Integer>();
List<Integer> list1 =new LinkedList<Integer>();
List<Integer> list2 =new ArrayList<>();
LinkedList list3 = new LinkedList();

 上述是常见的链表的声明方式

第一种,变量的声明类型和实际实现类型都是LinkedList,可直接调用 LinkedList 类中特有的方法,并且声明了泛型Integer,确保只能存储 Integer 类型的数据,编译期间就能进行类型检查,避免了类型转换异常。

第二种,声明类型是接口 List类型,实际实现的类型确实LinkedList,但只能调用 List 接口中定义的方法。如果需要使用 LinkedList 特有的方法(如队列或双端队列相关的方法),则需要显式地进行类型转换。同样使用了泛型 <Integer>,确保类型安全。

第三种声明类型是接口List,实现的是ArrayList类型,ArrayList 支持快速随机访问,时间复杂度为 O(1)。在数组中间插入或删除元素时需要移动元素,时间复杂度为 O(n);而 LinkedList 在任意位置添加或删除(假如已经有相应节点引用)通常更高效。

第四种实现的是原始类型(因为没有使用泛型),编译器不会对集合中的数据进行类型检查,

手搓链表

public class Linked {static class Node{int data;Node next;public Node(){};public Node(int data){this.data = data;this.next =null;}}public static class SingleLinkedList{private Node head;public void addFirst(int data){Node newNode = new Node(data);newNode.next = head;head = newNode;}public void addLast(int data){Node newNode = new Node(data);if(head ==null){head = newNode;return;}Node curr = head;while(curr.next != null){curr = curr.next;}curr.next = newNode;}public boolean remove(int data){if(head == null){//若链表为空,则删除失败return false;}if(head.data == data){//还要先判断头节点是否时要删除的head = head.next;return true;}Node curr = head;while(curr.next != null && curr.next.data != data){curr = curr.next;}if (curr.next != null) {curr.next = curr.next.next;return true;}return false;}public void printList() {Node curr = head;while (curr != null) {System.out.print(curr.data + " ");curr = curr.next;}System.out.println("null");}}public static void main(String[] args) {SingleLinkedList list = new SingleLinkedList();list.addFirst(4);list.addFirst(3);list.addFirst(2);list.addFirst(1);list.addLast(5);list.addLast(6);list.printList();//1 2 3 4 5 6 nulllist.remove(6);list.printList();//1 2 3 4 5 null}
}

反转链表

题意:反转一个单链表。

示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL,即右移

/*** 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) {// 如果链表为空,则直接返回nullif(head == null){return null;}// prev指针初始化为null,最后会成为反转后链表的头节点ListNode prev = null;// cur指针指向当前要处理的节点,开始时指向链表头headListNode cur = head;// temp用于保存当前节点cur的下一个节点,防止在改变指针关系后丢失引用ListNode temp = null;// 当当前节点不为空时,循环执行反转操作while (cur != null) {// 保存cur的下一个节点,防止链表断裂temp = cur.next; // 此时temp指向cur的下一节点// 将当前节点的next指针指向前一个节点,实现局部反转cur.next = prev; // 当前节点的next由原来的下一个节点变为前一个节点// 将prev移动到当前节点位置,为下一次反转操作做准备prev = cur;// 将cur后移到下一个节点,也就是之前保存的tempcur = temp;}// 循环结束后,prev指向反转后的链表头节点,返回它作为新的链表起点return prev;}
}

链表内两两交换

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

解1:

  • 创建一个虚拟头节点dummy指向head,定义current指针真相虚拟头节点
  • 进入循环体内,确定current每次后面都能有两个节点进行交换操作
  • 定义first和second分别指向第一个节点和第二个节点,
  • 然后让第二个节点指向第一个节点,第一个节点指向下一个要交换的第一个节点,最后让current指向交换后的第一个节点
  • 2,3,4循环操作,直至不够节点互换退出循环,返回虚拟头节点之后的head
public class Solution {public ListNode swapPairs(ListNode head) {// 创建哑结点,它的 next 指向原链表的头ListNode dummy = new ListNode(0);dummy.next = head;ListNode current = dummy;// 循环条件:当前结点后面至少有两个节点while (current.next != null && current.next.next != null) {// 定义要交换的两个节点ListNode first = current.next;ListNode second = current.next.next;// 交换节点:// 1. 先将 first 指向 second 的下一个节点first.next = second.next;// 2. second 指向 firstsecond.next = first;// 3. current 指向 second,完成与前面的连接current.next = second;// 移动 current,跳过刚才交换的两个节点current = first;}// 返回哑结点的 next,即新的头节点return dummy.next;}
}

解2:将链表转换为队列处理,在重建链表

import java.util.ArrayList;
import java.util.List;public class Solution {public ListNode swapPairs(ListNode head) {if (head == null || head.next == null) {return head;}// 1. 将链表节点存入数组List<ListNode> nodes = new ArrayList<>();ListNode current = head;while (current != null) {nodes.add(current);current = current.next;}// 2. 在数组中交换相邻节点for (int i = 0; i < nodes.size() - 1; i += 2) {// 交换nodes[i]与nodes[i+1]ListNode temp = nodes.get(i);nodes.set(i, nodes.get(i+1));nodes.set(i+1, temp);}// 3. 重建链表(根据交换后的数组重设每个节点的next指针)for (int i = 0; i < nodes.size() - 1; i++) {nodes.get(i).next = nodes.get(i + 1);}// 最后一个节点的next设为nullnodes.get(nodes.size() - 1).next = null;// 4. 返回新的链表头(数组中第一个元素)return nodes.get(0);}
}

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

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

相关文章

详解与FTP服务器相关操作

目录 什么是FTP服务器 搭建FTP服务器相关 ​编辑 Unity中与FTP相关的类 上传文件到FTP服务器 使用FTP服务器上传文件的关键点 开始上传 从FTP服务器下载文件到客户端 使用FTP下载文件的关键点 开始下载 关于FTP服务器的其他操作 将文件的上传&#xff0c;下载&…

Day92 | 灵神 | 二叉树 路径总和

Day92 | 灵神 | 二叉树 路径总和 112.路径总和 112. 路径总和 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 1.递归函数意义 如果在根节点为t的树中可以找到长度为target的路径就返回true&#xff0c;找不到就返回false 2.参数和返回值 bool tra(TreeNode …

探索鸿蒙应用开发:ArkTS应用执行入口揭秘

# 探索鸿蒙应用开发&#xff1a;ArkTS应用执行入口揭秘 在鸿蒙应用开发的领域中&#xff0c;ArkTS作为声明式开发语言&#xff0c;为开发者们带来了便捷与高效。对于刚接触鸿蒙开发的小伙伴来说&#xff0c;搞清楚ArkTS应用程序的执行入口是迈向成功开发的关键一步。今天&…

【Web API系列】Web Shared Storage API之WorkletSharedStorage深度解析与实践指南

前言 在现代Web开发领域&#xff0c;数据存储与隐私保护的矛盾始终存在。传统存储方案如LocalStorage和Cookies面临着日益严格的安全限制&#xff0c;而跨域数据共享的需求却在持续增长。正是在这样的背景下&#xff0c;Web Shared Storage API应运而生&#xff0c;其核心组件…

探索鸿蒙沉浸式:打造无界交互体验

一、鸿蒙沉浸式简介 在鸿蒙系统中&#xff0c;沉浸式是一种极具特色的设计理念&#xff0c;它致力于让用户在使用应用时能够全身心投入到内容本身&#xff0c;而尽可能减少被系统界面元素的干扰。通常来说&#xff0c;就是将应用的内容区巧妙地延伸到状态栏和导航栏所在的界面…

机器学习03——K近邻

K近邻算法学习笔记 一、算法简介 K近邻算法&#xff08;K - Nearest Neighbors&#xff0c;简称KNN&#xff09;是一种简单而有效的分类和回归算法。它的核心思想是“近朱者赤&#xff0c;近墨者黑”&#xff0c;即一个数据点的类别或值可以通过其周围最近的K个邻居来判断。K…

序列化 反序列化实例

在Python中&#xff0c; pickle 模块常用于实现对象的序列化和反序列化&#xff0c;以下是一个简单的实例&#xff1a; import pickle # 定义一个类 class Person: def __init__(self, name, age): self.name name self.age age # 创建一个Person对象 person Person("…

代码随想录算法训练营第十九天

LeetCode题目: 77. 组合216. 组合总和 III17. 电话号码的字母组合2537. 统计好子数组的数目(每日一题)516. 最长回文子序列1039. 多边形三角剖分的最低得分543. 二叉树的直径124. 二叉树中的最大路径和2246. 相邻字符不同的最长路径 其他: 今日总结 往期打卡 77. 组合 跳转: 7…

存算分离看场景

计算机行业是唯一一个比时装行业概念更多的行业。概念频出&#xff0c;最慢的话半年一定出一个&#xff0c;短的话半个月就能看到新的名词和技术甚至是概念。 存算分离的概念 我第一次听到存算分离时候还是从Hadoop上听到的。然后就去问什么是存算分离。听了讲解以后&#xf…

MCP协议,.Net 使用示例

服务器端示例 基础服务器 以下是一个基础的 MCP 服务器示例&#xff0c;它使用标准输入输出&#xff08;stdio&#xff09;作为传输方式&#xff0c;并实现了一个简单的回显工具&#xff1a; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.H…

智能语音处理+1.5使用PocketSphinxshinx实现语音转文本(100%教会)

欢迎来到智能语音处理系列的最后一篇文章&#xff0c;到这里,基本上语音处理是没问题了. 第一篇:智能语音处理1.1下载需要的库(100%实现)-CSDN博客 第二篇:智能语音识别1.2用SAPI实现文本转语音(100%教会)-CSDN博客 第三篇:智能语音处理1.3用SpeechLib实现文本转语音(100%教会)…

Kubernetes 节点摘除指南

目录 一、安全摘除节点的标准流程 1. 确认节点名称及状态 2. 标记节点为不可调度 3. 排空&#xff08;Drain&#xff09;节点 4. 删除节点 二、验证节点是否成功摘除 1. 检查节点列表 2. 检查节点详细信息 3. 验证 Pod 状态 三、彻底清理节点&#xff08;可选&#xf…

信息安全管理与评估2021年国赛正式卷答案截图以及十套国赛卷

2021年全国职业院校技能大赛高职组 “信息安全管理与评估”赛项 任务书1 赛项时间 共计X小时。 赛项信息 赛项内容 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 平台搭建与安全设备配置防护 任务1 网络平台搭建 任务2 网络安全设备配置与防护 第二…

3D语义地图中的全局路径规划!iPPD:基于3D语义地图的指令引导路径规划视觉语言导航

作者&#xff1a; Zehao Wang, Mingxiao Li, Minye Wu, Marie-Francine Moens, Tinne Tuytelaars 单位&#xff1a;鲁汶大学电气工程系&#xff0c;鲁汶大学计算机科学系 论文标题&#xff1a; Instruction-guided path planning with 3D semantic maps for vision-language …

《AI大模型应知应会100篇》第20篇:大模型伦理准则与监管趋势

第20篇&#xff1a;大模型伦理准则与监管趋势 摘要 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;尤其是大模型&#xff08;如GPT、PaLM等&#xff09;在自然语言处理、图像生成等领域的广泛应用&#xff0c;AI伦理问题和监管挑战日益凸显。本文将梳理当…

【Ai】dify:Linux环境安装 dify 详细步骤

一、什么是dify Dify 是一个 开源的大语言模型(LLM)应用开发平台,旨在帮助开发者快速构建基于 AI 的应用程序,例如智能对话助手、知识库问答、内容生成工具等。它提供了可视化的流程编排、模型集成、数据管理等功能,降低了开发门槛,支持快速迭代和部署。 核心功能与特点…

CentOS 操作系统下搭建 tsung性能测试环境

写在前面 为何这么安装,实际就是这么做的,这是经过好几次实践得出的经验总结。 这为了让大家更清楚的知道怎么安装 tsung性能测试环境,按步照搬的安装即可。 步骤 1、 下载软件安装包 CentOS-6.0-x86_64-bin-DVD1.iso jdk-6u4-linux-x64-rpm.bin erlang: otp_src_1…

Vulkanised

Vulkanised 1. About VulkanisedReferences The Premier Vulkan Developer Conference premier /ˈpremiə(r)/ n. 总理&#xff1b;(尤用于报章等) 首相&#xff1b;(加拿大的) 省总理&#xff1b;地区总理 adj. 第一的&#xff1b;首要的&#xff1b;最著名的&#xff1b;最…

C++之 动态数组

一、新建一个动态数组 数组名和下标操作符[]的组合可以被替换成一个指向该数组的基地址的指针和对应的指针运算&#xff1a; int a[20]; int *x a; 指针变量 x 指向数组 a 的地址&#xff0c; a[0] 和 *x 都代表数组的第一个元素。 于是&#xff0c;根据指针运算原则&…

ubuntu1804服务器开启ftp,局域网共享特定文件给匿名用户

要在 Ubuntu 18.04 上设置一个 FTP 服务器&#xff0c;满足以下要求&#xff1a; 允许匿名登录&#xff08;无需账号密码&#xff09;。指定分享特定目录下的文件。只允许只读下载。 可以使用 vsftpd&#xff08;Very Secure FTP Daemon&#xff09;来实现。以下是详细步骤&a…