240422 leetcode exercises

news2025/4/24 21:26:33

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/)
      • 🔁直接遍历
      • 🔁动归预处理
    • [LCR 136. 删除链表的节点](https://leetcode.cn/problems/shan-chu-lian-biao-de-jie-dian-lcof/)
      • 🔁直接遍历

237. 删除链表中的节点

有一个单链表的 head,我们想删除它其中的一个节点 node

给你一个需要删除的节点 node 。你将 无法访问 第一个节点 head

链表的所有值都是 唯一的,并且保证给定的节点 node 不是链表中的最后一个节点。

删除给定的节点。注意,删除节点并不是指从内存中删除它。这里的意思是:

  • 给定节点的值不应该存在于链表中。
  • 链表中的节点数应该减少 1。
  • node 前面的所有值顺序相同。
  • node 后面的所有值顺序相同。

​ 他是想说什么意思呢,就是在不给你整个链表的情况下,让你根据这个值来将这个节点删除。

​ 题目要求我们的函数被调用后输出整个链表,而我们又注意到所写函数是void类型,所以我们只需要执行删除该节点的操作即可。

​ 如果毫无思路,我们可以回忆一下删除链表的原理:

让上一个结点的next指针直接指向下一个节点。

​ 由于我们需要对链表进行遍历,才能获得前驱指针并执行上述操作。但是这里我们根本无法获取前驱指针。但是我们写的函数又不需要我们返回链表,所以如果让当前节点的值直接变成下一结点的值,也就是覆盖下一个节点,是不是就等价于删除了当前节点呢?

🔁节点覆盖法

假设链表在内存中是这样的(箭头表示 next 指针):

 → [ A | * ] → [ B | * ] → [ C | * ] → …
             ↑
       题目给出的node
  • [A|*] 表示当前节点的 val = Anext 指向下一个节点。
  • 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. 判断子序列

给定字符串 st ,判断 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 ≤ n0 ≤ 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

  1. 初始化末尾行

    for (int j = 0; j < SIGMA; j++) {
        nxt[n][j] = n;
    }
    

    位置 n 之后没有任何字符,所有字母的「下次出现」都标记为 n

  2. 自底向上填表

    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)×26int → O(n·Σ),这里 Σ=26。
  • 匹配阶段
    • 时间:遍历 s 一次,每步 O(1) 查表 → O(|s|)。

对于极多次查询同一个 t 是否包含不同 s 的变态情况,这种预处理 + 跳表的方法尤其高效。

LCR 136. 删除链表的节点

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。

返回删除后的链表的头节点。

示例 1:

输入:head = [4,5,1,9], val = 5
输出:[4,1,9]
解释:给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

示例 2:

输入:head = [4,5,1,9], val = 1
输出:[4,5,9]
解释:给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.

​ 我们使用前去节点遍历的方法来找到需要删除的值。

🔁直接遍历

​ 首先去掉目标只在头结点的情况。

​ 我们让前驱指针在下个节点的指针不指向空下个节点的值不等于目标值的情况下向前移动,在题目保证数据的情况下,一定会在指针走向尽头之前因为找到目标值而跳出这个循环。这时候我们让前驱指针所在的节点的next指针直接指向下一个节点的next指针,也就是下下一个节点的地址。

struct ListNode* deleteNode(struct ListNode* head, int val) {
    if (head -> val == val) return head -> next;
    struct ListNode* prev = head;
//不满足条件就遍历
    while( (prev -> next != NULL) && (prev -> next -> val != val)) prev = prev -> next;
//找到目标值就删
    if (prev -> next != NULL) prev -> next = prev -> next -> next; 

    return head;
}

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

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

相关文章

Appium安装 -- app笔记

调试环境&#xff1a;JDK&#xff08;java&#xff09; SDK&#xff08;android&#xff09; Node.js 雷神模拟器&#xff08;或 真机&#xff09; Appium&#xff08;Appium Server【内外件&#xff08;dos内件、界面化工具&#xff09;】、Appium Inspector&#xff09; p…

【OpenGL】OpenGL学习笔记-1:VS2019配置OpenGL开发环境

在Visual Studio 2019中可以通过手动配置库文件或NuGet包管理器快速安装的方法配置OpenGL环境&#xff0c;详细步骤如下&#xff1a; 一、打开VS2019&#xff0c;创建新的控制台项目 二、方法一&#xff1a;手动配置GLEW/GLFW/GLAD库 GLFW是窗口管理和输入事件的基础设施&…

集结号海螺捕鱼游戏源码解析(第二篇):水浒传捕鱼模块逻辑与服务器帧同步详解

本篇将全面解构“水浒传”子游戏的服务端核心逻辑、帧同步机制、鱼群刷新规则、客户端命中表现与服务器计算之间的协同方式&#xff0c;聚焦于 C 与 Unity3D 跨端同步的真实实现过程。 一、水浒传捕鱼模块资源结构 该模块包含三部分核心目录&#xff1a; 子游戏/game_shuihuz…

【音视频】FFmpeg内存模型

FFmpeg内存模型 从现有的Packet拷贝一个新Packet的时候&#xff0c;有两种情况&#xff1a; 两个Packet的buf引用的是同一数据缓存空间&#xff0c;这时候要注意数据缓存空间的释放问题&#xff1b;两个Packet的buf引用不同的数据缓存空间&#xff0c;每个Packet都有数据缓存…

小白自学python第一天

学习python的第一天 一、常用的值类型&#xff08;先来粗略认识一下~&#xff09; 类型说明数字&#xff08;number&#xff09;包含整型&#xff08;int&#xff09;、浮点型&#xff08;float&#xff09;、复数&#xff08;complex&#xff09;、布尔&#xff08;boolean&…

手动实现LinkedList

前言 大家好&#xff0c;我是Maybe。最近在学习数据结构中的链表&#xff0c;自己手动实现了一个LinkedList。我想与大家分享一下。 思维导图 代码部分 package Constant;public class constant {public static final String INDEX_IS_WRONG"输入的下标不合法"; }p…

maven的安装与配置、IDEA集成maven

一、maven的安装与配置环境变量 maven的下载与安装&#xff0c;配置环境变量与验证【附安装包3.6.1&#xff0c;3.8.8&#xff0c;3.9.9】-CSDN博客 参考资料&#xff1a;黑马程序员 二、IDEA集成 2.1 当前工程设置 1. 打开 Maven 设置路径&#xff1a;在 IDEA 中&#xf…

Axure中继器表格:实现复杂交互设计的利器

在产品原型设计领域&#xff0c;Axure凭借其强大的元件库和交互功能&#xff0c;成为设计师们手中的得力工具。其中&#xff0c;中继器元件在表格设计方面展现出了独特的优势&#xff0c;结合动态面板等元件&#xff0c;能够打造出功能丰富、交互体验良好的表格原型。本文将深入…

前端 JavaScript 处理流式响应的坑

给使用 JavaScript 的同学提个醒&#xff01; 浏览器端处理流式响应&#xff0c;想要完美体验 请使用 Fetch API。 Axios 无法使用stream来直接处理真正的流式响应&#xff08;但 Node.js 中可以使用 stream&#xff09;&#xff0c;这与浏览器底层 HTTP 请求实现的限制有关。 …

AI Agent认知框架(ReAct、函数调用、计划与执行、自问自答、批判修正、思维链、思维树详解和对比,最后表格整理总结

以下是主流AI Agent认知框架的详细说明、对比及表格总结&#xff1a; 1. 各认知框架详解 (1) ReAct (Reasoning Action) 定义&#xff1a;结合推理&#xff08;Reasoning&#xff09;和行动&#xff08;Action&#xff09;的循环过程。核心机制&#xff1a; 模型先推理&…

搭建TypeScript单元测试环境

我们在学习TypeScript的时候如果能够搭建一个单元测试的环境&#xff0c;那写些demo会很简单&#xff0c;下面我们使用jest来搭建一个单元测试环境 Jest 是一个由 Facebook 开发并开源的 JavaScript 测试框架&#xff0c;被广泛应用于前端和 Node.js 项目的单元测试。以下是关…

第十一届机械工程、材料和自动化技术国际会议(MMEAT 2025)

重要信息 官网&#xff1a;www.mmeat.net 时间&#xff1a;2025年06月23-25日 地点&#xff1a;中国-深圳 部分展示 征稿主题 智能制造和工业自动化 复合材料与高性能材料先进制造技术 自动化机器人系统 云制造与物联网集成 精密制造技术 智能生产线优化 实时数据分析与过…

leetcode 1143. Longest Common Subsequence

目录 题目描述 第一步&#xff0c;明确并理解dp数组及下标的含义 第二步&#xff0c;分析明确并理解递推公式 第三步&#xff0c;理解dp数组如何初始化 第四步&#xff0c;理解遍历顺序 代码 题目描述 这道题和第718题的区别就是&#xff0c;本题求的是最长公共子序列的长…

stack和queue的学习

stack的介绍 stack的文档介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其底层的容器&#xff0c;…

微服务Nacos组件的介绍、安装、使用

微服务Nacos组件的介绍、安装、使用 在微服务架构日渐普及的今天&#xff0c;服务注册与配置管理成了系统架构中的关键环节。阿里巴巴开源的 Nacos&#xff08;Naming and Configuration Service&#xff09;正是解决这一问题的利器。本文将为你全面介绍 Nacos 的概念、安装方…

SpringBoot_为何需要SpringBoot?

Spring Boot 出现前的开发困境 配置繁琐 大量的 XML 配置文件 Spring 是一个非常优秀的轻量级框架&#xff0c;但其配置却是重量级的需要编写大量的 XML 配置文件或注解配置&#xff0c;使项目配置复杂且难以维护配置文件中容易出现错误&#xff0c;且排查问题困难开发过程中…

格式工厂 v5.18最新免安装绿色便携版

前言 用它来转视频的时候&#xff0c;还能顺便给那些有点小瑕疵的视频修修补补&#xff0c;保证转出来的视频质量杠杠的。更厉害的是&#xff0c;它不只是转换那么简单&#xff0c;还能帮你把PDF合并成一本小册子&#xff0c;视频也能合并成大片&#xff0c;还能随心所欲地裁剪…

MQTTX + MCP:MQTT 客户端秒变物联网 Agent

引言&#xff1a;MQTTX 与 MCP 的融合 作为最受欢迎的 MQTT 客户端工具&#xff0c;MQTTX 在 1.12.0 beta 版本中集成了模型上下文协议&#xff08;MCP&#xff09;到 Copilot AI 功能中&#xff0c;显著提升了服务能力。这一融合让 MQTTX 转变为 MCP Host&#xff08;也就是发…

快手砍掉本地生活的门槛

一场本地商家的效率革命。 作者|景行 编辑|杨舟 “两斤鸡翅根七块九&#xff0c;两盒蓝莓九块钱&#xff0c;两公斤卫生纸十四块九一提。” 这是朝阳佳惠超市&#xff0c;在快手一则普通的短视频内容。 佳惠超市在辽宁省朝阳市有22家分店&#xff0c;打开佳惠超市的相关快手…

Python基础语法3

目录 1、函数 1.1、语法格式 1.2、函数返回值 1.3、变量作用域 1.4、执行过程 1.5、链式调用 1.6、嵌套调用 1.7、函数递归 1.8、参数默认值 1.9、关键字参数 2、列表 2.1、创建列表 2.2、下标访问 2.3、切片操作 2.4、遍历列表元素 2.5、新增元素 2.6、查找元…