240422 leetcode exercises
240422 leetcode exercises
@jarringslee
文章目录
- 240422 leetcode exercises
- [237. 删除链表中的节点](https://leetcode.cn/problems/delete-node-in-a-linked-list/)
- 🔁节点覆盖法
- [392. 判断子序列](https://leetcode.cn/problems/is-subsequence/)
- 🔁直接遍历
- 🔁动归预处理
237. 删除链表中的节点
有一个单链表的
head
,我们想删除它其中的一个节点node
。给你一个需要删除的节点
node
。你将 无法访问 第一个节点head
。链表的所有值都是 唯一的,并且保证给定的节点
node
不是链表中的最后一个节点。删除给定的节点。注意,删除节点并不是指从内存中删除它。这里的意思是:
- 给定节点的值不应该存在于链表中。
- 链表中的节点数应该减少 1。
node
前面的所有值顺序相同。node
后面的所有值顺序相同。
他是想说什么意思呢,就是在不给你整个链表的情况下,让你根据这个值来将这个节点删除。
题目要求我们的函数被调用后输出整个链表,而我们又注意到所写函数是void类型,所以我们只需要执行删除该节点的操作即可。
如果毫无思路,我们可以回忆一下删除链表的原理:
让上一个结点的next指针直接指向下一个节点。
由于我们需要对链表进行遍历,才能获得前驱指针并执行上述操作。但是这里我们根本无法获取前驱指针。但是我们写的函数又不需要我们返回链表,所以如果让当前节点的值直接变成下一结点的值,也就是覆盖下一个节点,是不是就等价于删除了当前节点呢?
🔁节点覆盖法
假设链表在内存中是这样的(箭头表示 next
指针):
→ [ A | * ] → [ B | * ] → [ C | * ] → …↑题目给出的node
[A|*]
表示当前节点的val = A
,next
指向下一个节点。node
指针正指向值为A
的节点,我们删掉它。
void deleteNode(struct ListNode* node) {*node = *node -> next; //哈哈就一行。
}
这一行等价于同时做了两件事:
node->val = node->next->val; // 把后继节点的值 B 复制到当前节点
node->next = node->next->next; // 把后继节点的 next 指针复制过来
我们看看这个操作带来了什么样的影响:
-
操作前
[ A | -> X ] [ B | -> Y ]node next_node
node->val = A
node->next
指向下一个节点(值 B)
-
执行
*node = *node->next;
node->val
变成了B
node->next
变成了node->next->next
(即原来 B 的 next,指向 C)
-
操作后
[ B | -> Y ] [ B | -> Y ] node (原 B 节点,已被孤立)
现在的链表里,从
…→node
开始… → [ B | * ] → [ C | * ] → …
——等价于把原来的 B 节点直接「搬到」A 的位置,然后把原 B 节点从链表里跳过去了。
这道题通过 复制后继节点 到当前节点,再跳过后继,实现了在不知道前驱的情况下删除节点的目标。关键一句 *node = *node->next;
,相当于同时做了赋值 val
和重连 next
,从链表逻辑上删掉了下一节点。
我简直是天才。
392. 判断子序列
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,
"ace"
是"abcde"
的一个子序列,而"aec"
不是)。进阶:
如果有大量输入的 S,称作 S1, S2, … , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
示例 1:
输入:s = "abc", t = "ahbgdc" 输出:true
示例 2:
输入:s = "axc", t = "ahbgdc" 输出:false
乍一看以为是包含字符串的问题,结果仔细一看,发现如果子序列的所有字符能被给出序列顺序地包含就符合条件。那么单次遍历的话就会简单很多。
🔁直接遍历
直接建立循环直接进行比较。
bool isSubsequence(char* s, char* t) {if (s[0] == '\0') return true;//排除空字符串情况int i = 0;for (int j = 0; t[j] != '\0'; j++){ //外循环移动大串if (s[i] == t[j]) i++;//如果发现该位置与小串相等,小串移动if (s[i] == '\0') return true;//循环内移动完了就成功}return false;
}
但是题目又说, “当 t 很长、要对它执行大量(10亿)子序列判断查询”,在这种变态情况下,我们想刚才那样愚蠢地遍历好像是有点笨拙了。但倘若我预处理目标串 t
,一次性记录好从每个位置往后字符 a…z
下次出现的位置,然后再用这个表快速「跳跃式」地在 t
中定位每个要匹配的 s[j]
,阁下又该如何应对?
🔁动归预处理
1. What is nxt
?
我们使用 (n+1)×26 的二维整型数组,用来存储 “从位置 i 开始,字母 'a'+c
下一次出现的位置”(其中 0 ≤ i ≤ n
,0 ≤ c < 26
)。
nxt[i][c]
的含义是,在字符串 t
中,从下标 i
(包含)往后,第一个字符等于 'a'+c
的位置索引;
如果再也不出现,即t
中再也没有字符 ('a'+c)
,我们就把它设为 n
(一个「越界」值)。
int (*nxt)[SIGMA] = malloc((n + 1) * sizeof(int[SIGMA]));
如果 t
中再也没有字符 ('a'+c)
,我们就把它设为 n
(一个「越界」值)。
这样,查找 “从位置 i 往后,‘x’ 下次出现在哪里” 就只需要读 nxt[i]['x'-'a']
一次,时间 O(1)。
2. 构造 nxt
表
-
初始化末尾行
for (int j = 0; j < SIGMA; j++) {nxt[n][j] = n; }
位置
n
之后没有任何字符,所有字母的「下次出现」都标记为n
。 -
自底向上填表
for (int i = n - 1; i >= 0; i--) {// 先拷贝后一行:默认后续出现位置和 i+1 一样memcpy(nxt[i], nxt[i + 1], SIGMA * sizeof(int));// 然后把 t[i] 这一个字符的“下次出现”位置修正为 i 自己nxt[i][t[i] - 'a'] = i; }
-
“如果我在 i+1 后面第一次见到 c,位置是谁?” →
nxt[i+1][c]
-
“但如果
t[i]
本身就是 c,就应该最近出现的位置是 i” → 覆盖nxt[i][c] = i
-
最终,
nxt[0][c]
恰好告诉我们「整个串中第一次出现 c 的位置」。
-
3. 用 nxt
快速匹配子序列
int i = -1;
for (int j = 0; s[j] && i < n; j++) {// 在 t 中,从 i+1 开始,寻找 s[j] 下一个出现的位置i = nxt[i + 1][s[j] - 'a'];
}
return i < n;
我们用 i
记录上一次匹配到 t 的哪个位置。若初始 i = -1
,表示还没匹配过任何字符;要找下一个,就从 i+1 = 0
开始搜。对于对每个 s[j]
,我们先计算 c = s[j]-'a'
,再读 pos = nxt[i+1][c]
。
如果 pos < n
,说明在 t
中找到了,就把 i = pos
,继续下一个 s[j+1]
。
如果 pos == n
,说明找不到,就会让 i >= n
,循环后自然跳出,最后 return false
。
整个过程只做了 |s|
步 O(1) 的跳跃查询,匹配结束后检查 i < n
即可判断 s
是否完全匹配为子序列。
时间和空间复杂度
- 预处理
- 时间:构造
nxt
需要做n+1
行,每行拷贝 26 个整数 → O(26·n) ≈ O(n)。- 空间:存
(n+1)×26
个int
→ O(n·Σ),这里 Σ=26。- 匹配阶段
- 时间:遍历
s
一次,每步 O(1) 查表 → O(|s|)。
对于极多次查询同一个 t
是否包含不同 s
的变态情况,这种预处理 + 跳表的方法尤其高效。
相关文章:
240422 leetcode exercises
240422 leetcode exercises jarringslee 文章目录 240422 leetcode exercises[237. 删除链表中的节点](https://leetcode.cn/problems/delete-node-in-a-linked-list/)🔁节点覆盖法 [392. 判断子序列](https://leetcode.cn/problems/is-subsequence/)🔁…...
【上位机——MFC】菜单类与工具栏
菜单类 CMenu,封装了关于菜单的各种操作成员函数,另外还封装了一个非常重要的成员变量m_hMenu(菜单句柄) 菜单使用 添加菜单资源加载菜单 工具栏相关类 CToolBarCtrl-》父类是CWnd,封装了关于工具栏控件的各种操作。 CToolBar-》父类是CC…...
Spark-SQL连接Hive总结及实验
一、核心模式与配置要点 1. 内嵌Hive 无需额外配置,直接使用,但生产环境中几乎不使用。 2. 外部Hive(spark-shell连接) 配置文件:将hive-site.xml(修改数据库连接为node01)、core-site.xml、…...
20.3 使用技巧9
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 20.3.13 DataGridView使用日期选择控件 有时为了输入方便或者固定日期格式,可以考虑点击DataGridView中某个单元格时出现…...
逻辑回归(Logistic Regression)
逻辑回归(Logistic Regression) 原理 通过 Sigmoid函数( σ ( z ) 1 1 e − z σ(z) \frac{1}{1e^{-z}} σ(z)1e−z1)将线性回归输出 z w T x b z w^Tx b zwTxb 映射到 [0,1] 区间输出值表示样本属于正类的概率&#…...
weblogic12 部署war包 项目运行报错
问题表现 weblogic12 部署war包项目成功,运行启动成功。但是在使用此项目的时候,点击任何功能都会报错,部分报错如下: at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.…...
重新定义户外防护!基于DeepSeek的智能展开伞棚系统技术深度解析
从“手动操作”到“感知决策”,AI重构城市空间弹性 全球极端天气事件频发,传统伞棚依赖人工展开/收纳,存在响应滞后(暴雨突袭时展开需3-5分钟)、抗风能力弱(8级风损毁率超60%)、空间利用率低等痛…...
Android15沉浸式界面顶部有问题
Android15沉浸式界面顶部有问题 往往开发人员的手机没这么高级,客户或者老板的手机是Android15的。 我明明就设了状态栏透明,我的手机也没问题。但Android15是有问题的。 先看下有问题的界面: 解决方案: 处理1: if (…...
git比较不同分支的不同提交文件差异
背景:只想比较某2个分支的某2次提交的差异,不需要带上父提交。 以commitA为基准,用commitB去比较差异 直接上代码: #!/bin/bashcommitAd347dad9f25fb17db89eadcec7ea0f1bacbf7d29 commitBa6cc0c1a863b5c56d5f48bff396e4cd6966e…...
ADB -> pull指令推送电脑文件到手机上
ADB Push命令 在Android开发中,ADB的push命令用于将文件从电脑传输到Android设备上,是开发和测试过程中的重要工具 基本语法 adb push <本地文件路径> <设备目标路径><本地文件路径>:必需参数,指定要推送的本…...
compat-openssl10和libnsl下载安装
在麒麟系统(如银河麒麟)中,compat-openssl10 和 libnsl 是一些软件(如 MySQL、Oracle 等)的依赖包,用于提供兼容性支持。以下是它们的下载方法: 1. 下载 compat-openssl10 compat-openssl10 是…...
射频功率放大器的核心工作机制与组件设计
以下是关于射频功率放大器工作原理的详细说明: 射频功率放大器(RF PA)是无线通信系统的核心组件,其功能基于能量转换与信号放大技术。它通过精确的能量控制与信号处理,将低功率射频信号转化为高功率输出,支…...
制作一款打飞机游戏12:初稿原型
当前进展 任务回顾:在之前,我们做了大量的规划和原型设计。我们创建了关卡,添加了侧向滚动和BOSS模式背景重复,还制作了一个紧凑的瓦片集。原型完成:我们完成了五个原型,基本实现了飞机飞行、滚动…...
C语言高频面试题——指针数组和数组指针
指针数组和数组指针是 C/C 中容易混淆的两个概念,以下是详细对比: 1. 指针数组(Array of Pointers) 定义:一个数组,其元素是 指针类型。语法:type* arr[元素个数]; 例如:int* ptr_a…...
爱普生TG-5006CG成为提升5G RedCap时钟同步精度的理想选择
在 5G 通信技术持续演进的进程中,5G RedCap(Reduced Capability,即降低能力)是5G技术中针对物联网场景优化的一种轻量化标准。它通过降低终端带宽、简化天线配置和调制方式等手段,大幅降低了终端设备的成本和功耗,同时继承了5G NR…...
用Mac M4构建多架构Docker镜像指南
使用Mac M4构建多架构Docker镜像指南 解决问题:WARNING: The requested image‘s platform (linux/amd64) does not match the detected host platform 📌 重点:为什么需要双栈架构镜像? 双栈架构镜像(同时支持ARM64和…...
PCB原理图解析(炸鸡派为例)
晶振 这是外部晶振的原理图。 32.768kHz 的晶振,常用于实时时钟(RTC)电路,因为它的频率恰好是一天的分数(32768 秒),便于实现秒计数。 C25 和 C24:两个 12pF 的电容,用于…...
GPU高效利用率实战揭秘:蓝耘元生代VS传统云平台的降维打击
文章目录 一、前言:AI算力革命与蓝耘元生代的崛起二、蓝耘元生代智算云核心架构解析2.1 技术基石:Kubernetes原生云与蜂巢式资源网络关键创新点: 2.2 核心功能模块 三、蓝耘元生代快速入门指南3.1 注册与资源申请3.2 实战案例:部署…...
EXCEL学习
一、基本计算 求和 SUM(区域):计算区域内数值总和。示例:SUM(A1:A10) 计算A1到A10的和。 平均值 AVERAGE(区域):计算区域内数值的平均值。示例:AVERAGE(B1:B10) 计算B1到B10的平均值。 计数 COUNT(区域):统计区域内非…...
PyTorch 线性回归详解:模型定义、保存、加载与网络结构
目录 前言一、pytorch框架线性回归1.1 pytorch模型的定义1.2 nn.Sequential()1.2.1 nn.Linear1.2.2 nn.Sequential 1.3 nn.ModuleList()1.4 nn.ModuleDict()1.5 nn.Module二、pytorch模型的保存2.1 保存模型的权重和其他参数2.1.1 torch.save()保存字典总结 前言 书接上文 自…...
基础服务系列-Jupyter Notebook 支持JavaScript
IJavascript is a Javascript kernel for the Jupyter notebook. npm install npm i -g ijavascript 报以上错误,执行以下命令。 npm i -g ijavascript --unsafe-perm 说明:npm会有生命周期,某个包会有生命周期来执行一些东西,…...
LabVIEW数据采集与传感系统
开发了一个基于LabVIEW的智能数据采集系统,该系统主要通过单片机与LabVIEW软件协同工作,实现对多通道低频传感器信号的有效采集、处理与显示。系统的设计旨在提高数据采集的准确性和效率,适用于各种需要高精度和低成本解决方案的工业场合。 项…...
如何编写单元测试
一.如何编写单元测试 下面我们以 fetchEnv 方法作为案例,编写一套完整的单元测试用例供读者参考 编写 fetchEnv 方法 ./src/utils/fetchEnv.ts 文件 /*** 环境参数枚举*/enum IEnvEnum {DEV dev, // 开发TEST test, // 测试PRE pre, // 预发PROD prod, // 生…...
【网络编程】从零开始彻底了解网络编程(三)
本篇博客给大家带来的是网络编程的知识点. 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅🚀 要开心要快乐顺便进步 TCP流…...
华为OD机试真题——数据分类(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式! 本文收录于专栏:《2025华为OD真题目录全流程解析/备考攻略/经验…...
3步拆解Linux内核源码的思维模型
3步拆解Linux内核源码的思维模型 ——从“不敢碰”到“庖丁解牛” 一、第一步:资料收集与框架搭建——像拼图一样找到“地图” 初看Linux内核源码的人,往往会被其千万行代码淹没。但正如登山前需要地形图,阅读内核前必须构建认知框架。 1…...
图像预处理-图像轮廓特征查找
其实就是外接轮廓,有了轮廓点就可以找到最上、最下、最左、最右的四个坐标(因为有xmin,xmax,ymin,ymax)。就可以绘制出矩形。 一.外接矩形 cv.boundingRect(轮廓点) - 返回x,y,w,h,传入一个轮廓的轮廓点,若有多个轮廓需…...
布尔差分法解析:从逻辑导数到电路优化
#布尔差分法解析:从逻辑导数到电路优化 一、背景数学知识:布尔代数基础 布尔变量与函数 在布尔代数中,变量的取值只有 0(表示假)和 1(表示真)。例如,一个布尔变量 x 可以取 0 或 1。…...
【NVIDIA】Isaac Sim 4.5.0 加载 Franka 机械臂
目录 一、NVIDIA Isaac Sim 4.5.0二、Isaac Sim 4.5.0 核心特性解析1. 基于 Omniverse 的跨平台仿真框架2. 模块化机器人开发架构3. 面向AI的强化学习支持 三、Isaac Sim 4.5.0 仿真环境搭建四、加载 Franka 机械臂1. Python源码2. 代码解析(按执行流程)…...
边缘计算场景下的GPU虚拟化实践(基于vGPU的QoS保障与算力隔离方案)
在智慧交通、工业质检等边缘计算场景中,GPU虚拟化技术面临严苛的实时性与资源隔离挑战。本文基于NVIDIA vGPU与国产算力池化方案,深入探讨多租户环境下算力隔离的工程实践,并给出可复用的优化策略。 一、边缘GPU虚拟化的核心痛点 动态负载…...
使用go-git同步文件到gitee
go-git是golang上纯go实现的git客户端,可用来同步文件到git仓库。 为什么不用gitee官方openapi,因为我需要强制推送覆盖,官方api不支持。 下面是一个通过xml.gz文件到gitee的代码示例 package clientimport ("fmt""gin-epg…...
HTTP 和 HTTPS 有什么区别?
文章目录 安全性端口号连接方式证书性能搜索引擎优化(SEO) HTTP(Hypertext Transfer Protocol,超文本传输协议)和 HTTPS(Hypertext Transfer Protocol Secure,超文本传输安全协议)都…...
【C++软件实战问题排查经验分享】UI界面卡顿 | CPU占用高 | GDI对象泄漏 | 线程堵塞 系列问题排查总结
目录 1、UI界面卡顿问题排查 2、软件CPU占用高问题排查 3、UI界面显示异常(GDI对象泄漏导致窗口绘制异常)问题排查 4、软件线程堵塞(包含线程死锁)问题排查 5、最后 C软件异常排查从入门到精通系列教程(核心精品专…...
ADB->查看某个应用的版本信息
查看某个应用版本的版本 在Android开发和测试过程中,我们经常需要获取应用的版本信息。本文将详细介绍如何使用ADB命令来查询特定应用(以com.example.myapplication为例)的版本号。 基本命令 要获取com.example.myapplication应用的版本名…...
Selenium的ActionChains:自动化Web交互的强大工具
目录 ActionChains简介环境准备基础操作鼠标操作键盘操作拖放操作高级用法常见问题与解决方案最佳实践总结 ActionChains简介 ActionChains是Selenium WebDriver提供的一个用于执行复杂用户交互的工具类。它允许我们模拟鼠标移动、点击、拖放以及键盘输入等操作,…...
管道位移自动化监测方案
一、背景 管道系统在区域性地质沉降作用下易形成非均匀应力场集中现象,诱发管体屈曲变形及环焊缝界面剥离等连续损伤累积效应,进而导致管道力学性能退化与临界承载能力衰减。传统人工巡检受限于空间覆盖度不足及数据采集周期长(≥72h…...
CompletableFuture并行处理任务
CompletableFuture并行处理任务 CompletableFuture基本概念与特性创建CompletableFuture实例 任务编排方法线程池选择默认线程池自定义线程池线程池配置建议 代码示例同步代码 CompletableFuture 基本概念与特性 异步执行: CompletableFuture允许任务在后台线程中…...
【系统架构设计师】信息安全的概念
目录 1. 5个基本要素2. 范围2.1 设备安全2.2 数据安全2.3 内容安全2.4 行为安全 3. 例题3.1 例题1 1. 5个基本要素 1.信息安全包括5个基本要素:机密性、完整性、可用性、可控性与可审查性。2.机密性:确保信息不暴露给未授权的实体或进程。3.完整性:只有得到允许的人才能修改数…...
华为云获取IAM用户Token的方式及适用分析
🧠 一、为什么要获取 IAM 用户 Token? 我们用一个生活中的比喻来解释👇: 🏢 比喻场景: 你要去一个 高级写字楼(华为云物联网平台) 办事(调用接口管理设备)&…...
齐次坐标系下的变换矩阵
理解齐次坐标系下的变换矩阵 文章目录 理解齐次坐标系下的变换矩阵1 引言2 齐次坐标系的简要介绍2.1 齐次坐标系的定义2.2 为什么需要齐次坐标系?2.3 齐次坐标系的特殊性质2.3.1 点和向量的区分2.3.2 投影变换 3 齐次坐标系下的变换矩阵3.1 二维变换矩阵平移变换缩放…...
web原生API AbortController网络请求取消方法使用介绍:防止按钮重复点击提交得最佳方案
在前端开发中,取消网络请求是一个常见的需求,尤其是在用户频繁操作或需要中断长时间请求的场景下。 AbortController 主要用于 优雅地管理和取消异步操作: 浏览器原生 API 一、代码解析 1. 创建 AbortController 实例 const controlle…...
74.搜索二维矩阵
题目: 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则&#x…...
基于Spring Boot+微信小程序的智慧农蔬微团购平台-项目分享
基于Spring Boot微信小程序的智慧农蔬微团购平台-项目分享 项目介绍项目摘要目录系统功能图管理员E-R图用户E-R图项目预览登录页面商品管理统计分析用户地址添加 最后 项目介绍 使用者:管理员、用户 开发技术:MySQLSpringBoot微信小程序 项目摘要 随着…...
机器学习-08-推荐算法-协同过滤
总结 本系列是机器学习课程的系列课程,主要介绍机器学习中关联规则 参考 机器学习(三):Apriori算法(算法精讲) Apriori 算法 理论 重点 MovieLens:一个常用的电影推荐系统领域的数据集 23张图&#x…...
03-HTML常见元素
一、HTML常见元素 常见元素及功能: 元素用途<h1>~<h6>标题从大到小<p>段落,不同段落会有间距<img>显示图片,属性src为图片路径,alt为图片无法显示时的提示文本<a>超链接,属性href为链…...
LangChain + 文档处理:构建智能文档问答系统 RAG 的实战指南
🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是Lang Chain 2、文档问答的典型应用场景 二、文…...
深入理解 DML 和 DQL:SQL 数据操作与查询全解析
深入理解 DML 和 DQL:SQL 数据操作与查询全解析 在数据库管理中,SQL(结构化查询语言)是操作和查询数据的核心工具。其中,DML(Data Manipulation Language,数据操作语言) 和 DQL&…...
头歌实训之SQL视图的定义与操纵
🌟 各位看官好,我是maomi_9526! 🌍 种一棵树最好是十年前,其次是现在! 🚀 今天来学习C语言的相关知识。 👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更…...
Excel/WPS表格中图片链接转换成对应的实际图片
Excel 超链图变助手(点击下载可免费试用) 是一款将链接转换成实际图片,批量下载表格中所有图片的转换工具,无需安装,双击打开即可使用。 表格中链接如下图所示: 操作方法: 1、双击以下图标&a…...
单例模式的使用场景 以及 饿汉式写法(智能指针)
单例模式的使用场景 以及 饿汉式写法(智能指针) 饿汉式:创建类时就已经创建好了类的实例(用智能指针实现)什么时候用单例模式:1. 全局配置管理2. 日志系统3. 资源管理器4. 硬件设备访问总结 饿汉式…...