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

【LeetCode 热题100】76. 最小覆盖子串的算法思路及python代码

76. 最小覆盖子串

给你一个字符串 s s s、一个字符串 t t t。返回 s s s 中涵盖 t t t 所有字符的最小子串。如果 s s s 中不存在涵盖 t t t 所有字符的子串,则返回空字符串 ‘ ‘ " ``\quad" ‘‘"

注意:

  • 对于 t t t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t t t 中该字符数量;
  • 如果 s s s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

示例 2:

输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。

示例 3:

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

个人解题思路:

我们可以利用“滑动窗口”的思想来解决这个问题。 具体步骤如下:

初始化:

  • 创建一个字典 remaining_target,记录字符串 t 中每个字符的出现次数。
  • 定义两个指针 indextemp_index,表示当前窗口的左右边界。
  • 定义变量 current_substring,用于记录当前窗口的子串。
  • 定义变量 min_substring,用于记录最小子串。
  • 定义变量 min_substring_length,用于记录最小子串的长度。
  • 定义布尔变量 found_all_chars,表示是否已找到目标字符串的所有字符。

遍历字符串:

代码首先初始化了目标字符串 t 的临时变量 remaining_target,并设置了变量来记录当前子串和最小子串。接着,代码遍历源字符串 s,对每个字符进行判断它是否在 remaining_target 中。如果在,则表示找到了目标字符串中的一个字符,remaining_target 中对应字符的数量减一。当在s 中找到第一个 t 的元素时,代码记录下当前的索引 temp_index,以备后续滑动index使用。 在遍历过程中,代码不断更新当前子串 current_substring,并在满足条件时更新最小子串 min_substring。当 remaining_target 的长度为零时,说明当前窗口已经包含了目标字符串的所有字符,代码会通过调整索引来优化子串的长度。最终,代码返回找到的最小子串。

python代码:

class Solution:def minWindow(self, s: str, t: str) -> str:# 初始化目标字符串的副本remaining_target = t# 初始化当前子串和最小子串current_substring = ''min_substring = ''min_substring_length = len(s)# 标记是否已找到目标字符串的所有字符found_all_chars = Falseindex = 0# 如果源字符串的长度小于目标字符串,直接返回空字符串if len(s) < len(t):return ''# 遍历源字符串while index < len(s):current_char = s[index]index += 1# 如果当前字符在目标字符串中if current_char in remaining_target:found_all_chars = True# 删除目标字符串中对应的字符remaining_target = remaining_target.replace(current_char, '', 1)# 如果目标字符串中剩余字符的长度为目标字符串长度减一,记录当前索引if len(remaining_target) == len(t) - 1:temp_index = index# 如果已找到目标字符串的所有字符if found_all_chars:current_substring += current_char  # 将当前字符添加到当前子串# 如果目标字符串的所有字符都已找到且当前子串长度小于最小子串长度if len(remaining_target) == 0 and len(current_substring) <= min_substring_length:min_substring = current_substringmin_substring_length = len(min_substring)# 如果目标字符串的所有字符都已找到if len(remaining_target) == 0:index = temp_indexremaining_target = tfound_all_chars = Falsecurrent_substring = ''return min_substring

时间复杂度:

  • 时间复杂度: O ( n ) O(n) O(n) 其中 n 是字符串 s s s 的长度。
    由于每个字符最多被指针 index 访问一次,因此时间复杂度为 O ( n ) O(n) O(n)
  • 空间复杂度: O ( k ) O(k) O(k) 其中 k 是字符集 t t t 的大小。
    需要额外的空间来存储字符串 remaining_targetcurrent_substring,其大小与字符集的大小成正比。

结果

python3的代码在用例165/168处提示超时,因此我用deepseek将代码转成了C++的形式提交了。以下是C++的提交结果和代码(C++的代码我没有检查):
请添加图片描述

#include <string>
#include <unordered_map>
#include <algorithm>class Solution {
public:std::string minWindow(std::string s, std::string t) {// 统计 t 中每个字符的出现次数std::unordered_map<char, int> t_count;for (char c : t) {t_count[c]++;}// 记录当前窗口内每个字符的出现次数std::unordered_map<char, int> window_count;int required = t_count.size(); // 需要匹配的字符种类数int formed = 0; // 当前窗口内已匹配的字符种类数int left = 0, right = 0; // 滑动窗口的左右指针int min_len = s.size() + 1; // 最小窗口的长度int min_left = 0; // 最小窗口的左指针while (right < s.size()) {// 扩展窗口char c = s[right];window_count[c]++;if (t_count.find(c) != t_count.end() && window_count[c] == t_count[c]) {formed++;}// 收缩窗口while (left <= right && formed == required) {c = s[left];if (right - left + 1 < min_len) {min_len = right - left + 1;min_left = left;}window_count[c]--;if (t_count.find(c) != t_count.end() && window_count[c] < t_count[c]) {formed--;}left++;}right++;}return min_len == s.size() + 1 ? "" : s.substr(min_left, min_len);}
};

官方解题思路

其核心思想也是使用滑动窗口的思想,结合哈希表来找到字符串 s s s 中包含字符串 t t t 所有字符的最小子串。

初始化:

  • 使用 unordered_map ori 来记录目标字符串 t 中每个字符的出现次数。
  • 定义两个指针 lr,分别表示当前窗口的左边界和右边界。
  • 定义变量 len 来记录当前找到的最小子串的长度,ansLansR 分别记录最小子串的起始和结束位置。

遍历字符串:

首先,右指针 r 向右移动,扩展窗口,直到窗口包含目标字符串 t 中的所有字符。每次右指针移动时,更新当前窗口中字符的计数。当窗口包含了 t 中所有字符时,尝试通过移动左指针 l 来收缩窗口,寻找更小的覆盖子串。每次收缩时,更新当前窗口中字符的计数。在每次收缩窗口时,检查当前窗口的大小是否小于之前记录的最小子串长度。如果是,则更新最小子串的起始和结束位置。遍历完成后,返回从 ansLansR 的子串。如果未找到符合条件的子串,则返回空字符串。

class Solution {
public:unordered_map <char, int> ori, cnt;bool check() {for (const auto &p: ori) {if (cnt[p.first] < p.second) {return false;}}return true;}string minWindow(string s, string t) {for (const auto &c: t) {++ori[c];}int l = 0, r = -1;int len = INT_MAX, ansL = -1, ansR = -1;while (r < int(s.size())) {if (ori.find(s[++r]) != ori.end()) {++cnt[s[r]];}while (check() && l <= r) {if (r - l + 1 < len) {len = r - l + 1;ansL = l;}if (ori.find(s[l]) != ori.end()) {--cnt[s[l]];}++l;}}return ansL == -1 ? string() : s.substr(ansL, len);}
};

时间复杂度:

  • 时间复杂度: O ( n ) O(n) O(n) 其中 n 是字符串 s 的长度。
    由于每个字符最多被指针 lr 各访问一次,因此时间复杂度为 O ( n ) O(n) O(n)
  • 空间复杂度: O ( k ) O(k) O(k) 其中 k 是字符集的大小。
    需要额外的空间来存储哈希表 ori,其大小与字符集的大小成正比。

结果

请添加图片描述

算法分析

同样的思路,我的算法要比官方题解效率更高,主要可能有以下两方面的原因:

数据结构的选择:

官方题解: 使用了 unordered_map 来记录字符的出现次数。
我的算法: 使用了更高效的数据结构,即临时变量和数组。
影响: 对于字符集大小固定的情况,使用临时变量数组可以减少哈希计算的开销,从而提高效率。

字符串操作:

官方题解: 每次收缩窗口时,会频繁地进行字符串截取操作。
我的算法:通过记录子串的起始位置和长度,避免了多次字符串截取。
影响: 减少字符串操作可以降低时间复杂度,提升性能。

相关文章:

【LeetCode 热题100】76. 最小覆盖子串的算法思路及python代码

76. 最小覆盖子串 给你一个字符串 s s s、一个字符串 t t t。返回 s s s 中涵盖 t t t 所有字符的最小子串。如果 s s s 中不存在涵盖 t t t 所有字符的子串&#xff0c;则返回空字符串 ‘ ‘ " \quad" ‘‘" 。 注意&#xff1a; 对于 t t t 中重复…...

力扣-回溯-17 电话号码的字母组合

思路 和之前的回溯不同的是&#xff0c;要遍历完所有的数字&#xff0c;并且在单层递归逻辑里需要遍历一整个字符串 代码 class Solution { public:vector<string> letters {"", "", "abc", "def", "ghi", "…...

[AHOI2018初中组] 分组---贪心算法

贪心没套路果真如此。 题目描述 小可可的学校信息组总共有 n 个队员&#xff0c;每个人都有一个实力值 ai​。现在&#xff0c;一年一度的编程大赛就要到了&#xff0c;小可可的学校获得了若干个参赛名额&#xff0c;教练决定把学校信息组的 n 个队员分成若干个小组去参加这场…...

知识图谱-学习计划

✨知识图谱知识学习&#xff0c;给我点赞&#xff01;&#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f;什么是知识图谱&#xff1f; 知识图谱是一种通过图结构表示知识的技术&#xff0c;它可以帮助我们更清晰地理解和组织信息。无论是学习、工作还是生活&#xff0c;知…...

网安作业3

标准版 接口ip配置 r2 [r2]interface GigabitEthernet 0/0/0 [r2-GigabitEthernet0/0/0]ip address 13.0.0.3 24 [r2-GigabitEthernet0/0/0]interface GigabitEthernet 0/0/1 [r2-GigabitEthernet0/0/1]ip address 100.1.1.254 24 [r2-GigabitEthernet0/0/1]interface Gigab…...

快速提升网站收录:内容创作的艺术

快速提升网站收录&#xff0c;内容创作是关键。以下是一些关于内容创作以提升网站收录的艺术性建议&#xff1a; 一、关键词研究与优化 选择长尾关键词&#xff1a;进行深入的关键词研究&#xff0c;选择既符合网站主题又具有一定搜索量的长尾关键词。这些关键词通常更具体&a…...

【C语言】CreateFile函数用法介绍

目录 一、函数原型与基本功能 二、参数详解 1. lpFileName&#xff08;文件路径&#xff09; 2. dwDesiredAccess&#xff08;访问权限&#xff09; 补充说明 3. dwShareMode&#xff08;共享模式&#xff09; 5. dwCreationDisposition&#xff08;创建策略&#xff09…...

蓝桥杯好数

样例输入&#xff1a; 24 输出&#xff1a;7 输入&#xff1a;2024 输出&#xff1a; 150 思路&#xff1a;本题朴素方法的时间复杂度是O(n * log10(n)) &#xff0c;不超时。主要考察能否逐位取数&#xff0c;注意细节pi&#xff0c;这样不会改变i,否则会导致循环错误。 #in…...

SOME/IP--协议英文原文讲解10

前言 SOME/IP协议越来越多的用于汽车电子行业中&#xff0c;关于协议详细完全的中文资料却没有&#xff0c;所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块&#xff1a; 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 4.2.2 Req…...

欢乐力扣:赎金信

文章目录 1、题目描述2、 代码 1、题目描述 赎金信&#xff0c;给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。magazine 中的每个字符只能在…...

【量化科普】Standard Deviation,标准差

【量化科普】Standard Deviation&#xff0c;标准差 &#x1f680;&#x1f680;&#x1f680;量化软件开通&#x1f680;&#x1f680;&#x1f680; &#x1f680;&#x1f680;&#x1f680;量化实战教程&#x1f680;&#x1f680;&#x1f680; 在量化投资领域&#xf…...

stm32单片机个人学习笔记15(I2C通信协议)

前言 本篇文章属于stm32单片机&#xff08;以下简称单片机&#xff09;的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 STM32入门教程-2023版 细…...

网络安全防护

一&#xff1a;物理安全防护 直接的物理破坏所造成的损失远大于通过网络远程攻击 提高物理安全需关注的问题&#xff1a; 1: 服务器和安全设备是否放置在上锁的机房内&#xff1f; 2: 网络设备是否被保护和监控&#xff1f; 3: 是否有无关人员单独在敏感区域工作&…...

YOLOV7的复现过程

复现 YOLOv7 代码的步骤相对清晰&#xff0c;主要分为以下几个部分&#xff1a; 环境准备克隆 YOLOv7 仓库准备数据集训练模型验证和测试推理&#xff08;Inference&#xff09; 下面是一个简化的流程来帮助你复现 YOLOv7 代码&#xff1a; 1. 环境准备 首先&#xff0c;你…...

uniapp实现app的pdf预览

实现效果 文件准备 static下添加该pdf文件&#xff08;下载地址&#xff1a;https://gitee.com/shallow-winds/resource_package/tree/master/%E6%96%B9%E6%B3%95%E4%B8%80/html&#xff09; 使用web-view进行展示&#xff1a; 在这里插入代码片 <web-view :src"u…...

用Java创建一个验证码的工具类

在Java中创建一个验证码工具类&#xff0c;可以通过以下代码实现。该工具类支持生成包含字母和数字的随机验证码图片&#xff0c;并添加干扰线和噪点以提高安全性。以下是详细实现&#xff1a; 完整代码实现 import javax.imageio.ImageIO; import java.awt.*; import java.aw…...

uvm中的激励是如何发送出去的

在UVM中&#xff0c;Sequence生成的激励&#xff08;Transaction&#xff09;通过以下协作流程发送到Driver并最终驱动到DUT&#xff0c;其核心机制如下&#xff1a; --------------- --------------- ------------ ----- | Sequence | → | Seque…...

一只企鹅如何改变世界

一、历史的转折点:一只企鹅如何改变世界 1991年,芬兰大学生Linus Torvalds在邮件列表中写道:“我正在做一个自由的操作系统(只是爱好,不会像GNU那样庞大专业)”。这个后来被称为Linux内核的项目,与GNU项目的结合,点燃了开源运动的燎原之火。 关键演化: 1996年:Tux企…...

拦截器VS过滤器:Spring Boot中请求处理的艺术!

目录 一、拦截器&#xff08;Interceptor&#xff09;和过滤器&#xff08;Filter&#xff09;&#xff1a;都是“守门员”&#xff01;二、如何实现拦截器和过滤器&#xff1f;三、拦截器和过滤器的区别四、执行顺序五、真实的应用场景六、总结 &#x1f31f;如果喜欢作者的讲…...

C语言预处理学习笔记

1. 预处理器的功能 预处理器&#xff08;Preprocessor&#xff09;在编译C语言程序之前对源代码进行预处理。预处理指令以#号开头&#xff0c;主要包括文件包含、宏定义、条件编译等功能。 2. 文件包含 文件包含功能用于在一个文件中包含另一个文件的内容&#xff0c;通常用…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

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 开发者设计的强大库&#xff…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...

多元隐函数 偏导公式

我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式&#xff0c;给定一个隐函数关系&#xff1a; F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 &#x1f9e0; 目标&#xff1a; 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z​、 …...