练习题(2024/5/13)
1移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1 输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7 输出:[]
提示:
- 列表中的节点数目在范围
[0, 104]内 1 <= Node.val <= 500 <= val <= 50
思路:
使用虚拟头结点的方法来简化链表的删除操作。首先,创建一个值为0的虚拟头结点,然后将其指向原始链表的头部。接着,使用一个指针 cur 遍历整个链表,当 cur->next 的值等于目标值 val 时,删除当前节点的下一个节点,并将当前节点指向下下个节点;否则,将 cur 指针向后移动一个节点。最后,返回虚拟头结点的下一个节点作为新的链表头部。
代码:
class Solution {
public:// 删除链表中值为 val 的所有节点ListNode* removeElements(ListNode* head, int val) {// 设置一个虚拟头结点ListNode* dummyHead = new ListNode(0);// 将虚拟头结点指向 head,这样方便后面做删除操作dummyHead->next = head;ListNode* cur = dummyHead;// 遍历链表while (cur->next != NULL) {// 如果当前节点的下一个节点的值等于 val,则删除下一个节点if(cur->next->val == val) {ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;} else {cur = cur->next;}}// 更新 head 指针head = dummyHead->next;// 删除虚拟头结点delete dummyHead;return head;}
};
2设计链表
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
实现 MyLinkedList 类:
MyLinkedList()初始化MyLinkedList对象。int get(int index)获取链表中下标为index的节点的值。如果下标无效,则返回-1。void addAtHead(int val)将一个值为val的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。void addAtTail(int val)将一个值为val的节点追加到链表中作为链表的最后一个元素。void addAtIndex(int index, int val)将一个值为val的节点插入到链表中下标为index的节点之前。如果index等于链表的长度,那么该节点会被追加到链表的末尾。如果index比长度更大,该节点将 不会插入 到链表中。void deleteAtIndex(int index)如果下标有效,则删除链表中下标为index的节点。
示例:
输入 ["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"] [[], [1], [3], [1, 2], [1], [1], [1]] 输出 [null, null, null, null, 2, null, 3]解释 MyLinkedList myLinkedList = new MyLinkedList(); myLinkedList.addAtHead(1); myLinkedList.addAtTail(3); myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3 myLinkedList.get(1); // 返回 2 myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3 myLinkedList.get(1); // 返回 3
提示:
0 <= index, val <= 1000- 请不要使用内置的 LinkedList 库。
- 调用
get、addAtHead、addAtTail、addAtIndex和deleteAtIndex的次数不超过2000。
思路:
这道题的要求有五个:
- 获取链表第index个节点的数值
- 在链表的最前面插入一个节点
- 在链表的最后面插入一个节点
- 在链表第index个节点前面插入一个节点
- 删除链表的第index个节点
-
定义节点结构体: 开始先定义了一个嵌套的节点结构体
LinkedNode,它包含两个成员变量,一个是节点的值val,另一个是指向下一个节点的指针next。 -
初始化链表: 在
MyLinkedList类的构造函数中,创建了一个虚拟头结点_dummyHead,它的val为0,next为nullptr,用来简化链表的操作。同时初始化了链表的大小_size为0。 -
获取节点值:
get(int index)函数用于获取链表中第index个节点的值。通过判断index是否合法,然后从虚拟头结点开始遍历找到目标节点,并返回其值。 -
在头部插入节点:
addAtHead(int val)函数用于在链表的头部插入一个新节点。先创建一个新节点,然后将新节点的next指向原头结点,再将虚拟头结点的next指向新节点,最后更新链表大小。 -
在尾部插入节点:
addAtTail(int val)函数用于在链表的尾部插入一个新节点。从虚拟头结点开始遍历找到最后一个节点,然后将其next指向新节点,最后更新链表大小。 -
在指定位置插入节点:
addAtIndex(int index, int val)函数用于在指定位置插入一个新节点。首先判断插入位置的合法性,然后从虚拟头结点开始遍历找到目标位置的前一个节点,插入新节点,并更新链表大小。 -
删除指定位置的节点:
deleteAtIndex(int index)函数用于删除指定位置的节点。同样需要判断位置的合法性,然后找到目标位置的前一个节点,将其next指针跳过待删除节点,删除节点并释放内存,最后更新链表大小。
代码:
class MyLinkedList {
public:// 定义链表节点结构体struct LinkedNode {int val; // 节点的值LinkedNode* next; // 指向下一个节点的指针LinkedNode(int val):val(val), next(nullptr){}
//LinkedNode(int val) : val(val), next(nullptr) {}这行代码创建了一个LinkedNode结构体的构造函数,它接受一个整数参数val,并将val赋值给节点的val成员,同时将next指针初始化为nullptr。};// 初始化链表MyLinkedList() {_dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点_size = 0;}// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点int get(int index) {if (index > (_size - 1) || index < 0) { // 判断index是否合法return -1;}LinkedNode* cur = _dummyHead->next; // 从第一个真正的节点开始while(index--) { // 循环找到第index个节点cur = cur->next;}return cur->val; // 返回该节点的值}// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点void addAtHead(int val) {LinkedNode* newNode = new LinkedNode(val); // 创建一个新节点newNode->next = _dummyHead->next; // 将新节点的next指针指向原来的第一个节点_dummyHead->next = newNode; // 将虚拟头结点指向新节点_size++; // 更新链表长度}// 在链表最后面添加一个节点void addAtTail(int val) {LinkedNode* newNode = new LinkedNode(val); // 创建一个新节点LinkedNode* cur = _dummyHead; // 从虚拟头结点开始遍历while(cur->next != nullptr){ // 找到最后一个节点cur = cur->next;}cur->next = newNode; // 将新节点加在最后一个节点之后_size++; // 更新链表长度}// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点// 如果index大于链表的长度,则返回空// 如果index小于0,则在头部插入节点void addAtIndex(int index, int val) {if(index > _size) return; // 如果index大于链表长度,则直接返回if(index < 0) index = 0; // 如果index小于0,则在头部插入节点LinkedNode* newNode = new LinkedNode(val); // 创建一个新节点LinkedNode* cur = _dummyHead; // 从虚拟头结点开始遍历while(index--) { // 找到第index个节点的前一个节点cur = cur->next;}newNode->next = cur->next; // 将新节点的next指针指向当前节点的next指针指向的节点cur->next = newNode; // 将当前节点的next指针指向新节点_size++; // 更新链表长度}// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的void deleteAtIndex(int index) {if (index >= _size || index < 0) { // 如果index大于等于链表长度或小于0,则直接返回return;}LinkedNode* cur = _dummyHead; // 从虚拟头结点开始遍历while(index--) { // 找到第index个节点的前一个节点cur = cur ->next;}LinkedNode* tmp = cur->next; // 保存待删除节点cur->next = cur->next->next; // 将待删除节点的前一个节点指向待删除节点的后一个节点delete tmp; // 释放待删除节点的内存tmp=nullptr; // 将指向待删除节点的指针置空,避免成为野指针_size--; // 更新链表长度}private:int _size; // 链表长度LinkedNode* _dummyHead; // 虚拟头结点指针
};
3有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
示例 2:
输入: s = "rat", t = "car" 输出: false
提示:
1 <= s.length, t.length <= 5 * 104s和t仅包含小写字母
思路:
-
记录字母出现次数: 首先,代码使用一个长度为26的整型数组
record来记录每个字母出现的次数,数组的索引与字母的ASCII码对应,这样可以将小写字母映射到record数组的相应位置。 -
遍历第一个字符串: 然后,代码遍历字符串
s,对于每个字符,将其出现的次数记录在record数组中相应的位置。 -
遍历第二个字符串: 接着,代码同样遍历字符串
t,对于每个字符,将其出现的次数从record数组中相应位置减去。 -
检查记录数组: 最后,代码遍历
record数组,如果发现有任何一个位置的值不为0,说明两个字符串中有不同数量的某个字母,即它们不是字母异位词,返回false;如果record数组所有位置的值都为0,则说明两个字符串是字母异位词,返回true
代码:
class Solution {
public:// 判断两个字符串是否是字母异位词bool isAnagram(string s, string t) {// 记录每个字母出现的次数的数组,初始值都为0int record[26] = {0};// 遍历字符串s,统计每个字母出现的次数for (int i = 0; i < s.size(); i++) {// 将字母映射到record数组的索引,统计出现次数record[s[i] - 'a']++;}// 遍历字符串t,统计每个字母出现的次数for (int i = 0; i < t.size(); i++) {// 将字母映射到record数组的索引,减去出现次数record[t[i] - 'a']--;}// 遍历record数组,如果有非零值,则说明不是字母异位词for (int i = 0; i < 26; i++) {if (record[i] != 0)return false;}// 如果record数组所有元素都为0,则说明是字母异位词return true;}
};
4两个数组的交集
给定两个数组 nums1 和 nums2 ,返回 它们的
交集
。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出:[9,4] 解释:[4,9] 也是可通过的
提示:
1 <= nums1.length, nums2.length <= 10000 <= nums1[i], nums2[i] <= 1000
思路:
代码:
class Solution {
public:// 求两个数组的交集vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {// 用于存储结果的无序集合unordered_set<int> result_set;// 将 nums1 转化为无序集合,方便进行查找unordered_set<int> nums_set(nums1.begin(), nums1.end());// 遍历 nums2,查找是否存在于 nums1 中,存在则加入结果集合for (int num : nums2) {if (nums_set.find(num) != nums_set.end()) {result_set.insert(num);}}// 将结果集合转化为数组并返回return vector<int>(result_set.begin(), result_set.end());}
};
相关文章:
练习题(2024/5/13)
1移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 示例 1: 输入:head [1,2,6,3,4,5,6], val 6 输出:[1,2,3,4,5]示例 2: …...
LeetCode—设计循环队列(两种方法)
1.题目 2.思路一(数组) 通过数组进行模拟,通过操作数组的索引构建一个虚拟的首尾相连的环。再循环队列结构中,设置一个队首head和队尾tail,数组的大小固定为k。 初步分析:存在缺陷 改善假溢出问题&#…...
python “名称空间和作用域” 以及 “模块的导入和使用”
七、名称空间和作用域 可以简单理解为存放变量名和变量值之间绑定关系的地方。 1、名称空间 在 Python 中有各种各样的名称空间: 全局名称空间:每个程序的主要部分定义了全局的变量名和变量值的对应关系,这样就叫做全局名称空间 局部名称…...
Pycharm导入自定义模块报红
文章目录 Pycharm导入自定义模块报红1.问题描述2.解决办法 Pycharm导入自定义模块报红 1.问题描述 Pycharm 导入自定义模块报红,出现红色下划线。 2.解决办法 打开【File】->【Setting】->【Build,Execution,Deployment】->【Console】->【Python Con…...
LLMs之KG-RAG:KG-RAG(基于知识图谱的RAG系统)的简介(可以解决多跳问题/同时支持结构化和非结构化数据查询)、经验技巧、案例应用之详细攻略
LLMs之KG-RAG:KG-RAG(基于知识图谱的RAG系统)的简介(可以解决多跳问题/同时支持结构化和非结构化数据查询)、经验技巧、案例应用之详细攻略 背景痛点:传统的基于向量相似度检索的RAG模型回答多环(多步)问题的能力有限,无法同时处理来自多个文…...
综合模型及应用(图论学习总结部分内容)
文章目录 前言六、综合模型及应用(以题目总结为主)分层图思想(包括拆点建图) e g 1 : 通信线路 eg1:通信线路 eg1:通信线路[A-Telephone Lines](https://ac.nowcoder.com/acm/contest/1055/A)(蓝书例题) e g 2 : 小雨坐地铁 eg2:小雨坐地铁 eg2:小雨坐地铁 [1012-小雨坐…...
2025考研专业课、英语、数学、政治视频大全,整理全了!
考研季又到了,备考的小伙伴们,你们准备好了吗? 时间管理 考研是一场与时间的赛跑,合理安排时间,让复习更高效! - 制定详细的学习计划,每天、每周、每月都有明确目标 - ♂️ 保持一定的学习…...
设计模式之策略模式(一)
背景: 下单时有很多情况,有的是用户下单,有的是卡密下单,有的是下游下单,有的是需要唤起支付,有的不需要支付,这样就需要写很多下单接口,下面使用策略模式优化这种情况 代码结构 com.example.order ├── controller │ └── OrderController.java ├── service │ …...
常见网络攻击及解决方案
网络安全是开发中常常会遇到的情况,为什么会遇到网络攻击,网络攻击是如何进行的,如何抵御网络攻击,都是我们需要思考的问题。 为什么会遇到网络攻击? 以下是一些主要的因素: 技术漏洞:软件或操…...
【挑战30天首通《谷粒商城》】-【第一天】【10 番外篇】 解决docker 仓库无法访问 + MobaXterm连接VirtualBox虚拟机
文章目录 课程介绍 1、解决docker 仓库无法访问 2、 MobaXterm连接VirtualBox虚拟机 Stage 1:下载MobaXterm选择适合你的版本 Stage 2:vagrant ssh 连接,开启ssh访问 Stage 2-1:su获取root账号权限,输入密码(默认vagra…...
【C++】每日一题 17 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 可以使用回溯法来解决这个问题。首先定义一个映射关系将数字与字母对应起来…...
vue预览PDF文件的几种方法
1.使用iframe标签预览PDF文件 1.1页面结构 html <iframe:src"fileUrl"id"iframeBox"ref"iframeRef"frameborder"0"style"width: 100%; height: 800px"></iframe>1.2 js代码 export default {data() {return {…...
深度学习入门到放弃系列 - 阿里云人工智能平台PAI部署开源大模型chatglm3
通过深度学习入门到放弃系列 - 魔搭社区完成开源大模型部署调用 ,大概掌握了开源模型的部署调用,但是魔搭社区有一个弊端,关闭实例后数据基本上就丢了,本地的电脑无法满足大模型的配置,就需要去租用一些高性价比的GPU机…...
GPT-4o,AI实时视频通话丝滑如人类,Plus功能免费可用
不开玩笑,电影《她》真的来了。 OpenAI最新旗舰大模型GPT-4o,不仅免费可用,能力更是横跨听、看、说,丝滑流畅毫无延迟,就像在打一个视频电话。 现场直播的效果更是炸裂: 它能感受到你的呼吸节奏…...
【优选算法】——Leetcode——202—— 快乐数
目录 1.题目 2. 题⽬分析: 3.简单证明: 4. 解法(快慢指针): 算法思路: 补充知识:如何求⼀个数n每个位置上的数字的平⽅和。 总结概括 5.代码实现 1.C语言 2.C 1.题目 202. 快乐数 编写一个算法来…...
华大基因CEPO-尹烨说学习与生活
怎么去面对生活和事业中的不确定性? 尹烨说,人类能够对抗不确定性的唯一的办法是,去让自己充电。 主持人问他,“和你同年的也有很多人,他们也可能也在学习,你怎么就能够脱颖而出呢?” 他说&am…...
C#中json数据序列化和反序列化的最简单方法(C#对象和字符串的相互转换)
文章目录 将C#对象转换为json字符串Newtonsoft模块的安装用Newtonsoft将对象转换为json字符串 将json字符串转换为C#对象 将C#对象转换为json字符串 本介绍将基于C#中的第三方库Newtonsoft进行,因此将分为Newtonsoft模块的安装和使用两部分。该模块的优势在于只需要…...
logback 日志脱敏
工具类 CustomLogbackPatternLayoutEncoder.java import ch.qos.logback.classic.encoder.PatternLayoutEncoder;public class CustomLogbackPatternLayoutEncoder extends PatternLayoutEncoder {/*** 正则替换规则*/private LogbackReplaces replaces;/*** 使用自定义 MyLog…...
element-ui的表单中,输入框、级联选择器的长度设置
使用<el-col>控制输入框的长度 <el-form-item label"姓名" label-width"80px"><el-col :span"15"><el-input v-model"form.name" autocomplete"off"></el-input></el-col></el-form…...
深入了解 npm:Node.js 包管理工具详解
文章目录 一、npm 基本概念1.1 什么是 npm?1.2 package.json 文件 二、npm 常用命令2.1 初始化项目2.2 安装依赖2.2.1 安装单个包2.2.2 全局安装包2.2.3 安装开发依赖 2.3 移除依赖2.4 更新依赖2.5 查看已安装的包2.6 发布包 三、npm 高级用法3.1 使用 npm scripts3…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
