《算法题讲解指南:优选算法-滑动窗口》--15.串联所有单词的子串,16.最小覆盖子串

《算法题讲解指南:优选算法-滑动窗口》--15.串联所有单词的子串,16.最小覆盖子串

🔥小叶-duck个人主页

❄️个人专栏《Data-Structure-Learning》

《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--从优选到贪心

未择之路,不须回头
已择之路,纵是荆棘遍野,亦作花海遨游


目录

15. 串联所有单词的子串

题目链接:

题目描述:

题目示例:

解法(滑动窗口+哈希表):

算法思路:

C++算法代码:

算法总结及流程解析:

16. 最小覆盖子串

题目链接:

题目描述:

题目示例:

解法 (滑动窗口+哈希表):

算法思路:

算法流程:

C++算法代码:

算法总结及流程解析:

结束语


15. 串联所有单词的子串

题目链接:

30. 串联所有单词的子串 - 力扣(LeetCode)

题目描述:

题目示例:

解法(滑动窗口+哈希表):

算法思路:
  • 如果我们把每一个单词看成一个个字母,问题就变成了找到【字符串中所有的字母的异位词】。无非就是之前处理的对象是一个个字符,我们这里处理的对象是一个一个的单词。

有以下几点不同:

  • 哈希表需要使用 hash<string,int>
  • left 和 right 移动的步长是单词的长度(len)
  • 滑动窗口执行的次数也是 len 次

C++算法代码:

class Solution { public: vector<int> findSubstring(string s, vector<string>& words) { //解法:滑动窗口 + 哈希表(容器) vector<int> ret; unordered_map<string, int> hash1; //统计 words 中所有单词出现的频次 //string表示存放的数据是string类型,int表示数据存放的次数 for(auto e : words) { hash1[e]++; } int len = words[0].size(); //len为 words 中每个字符串的长度 int m = words.size(); //m为 words 的长度,目的是为了和 count 相比较 int left = 0; int right = 0; for(int i = 0; i < len; i++) { unordered_map<string, int> hash2;//存放s中的子串 //放到第一个for循环中目的是:每轮判断完成后hash2需要进行重置 //避免上一轮hash2中存放的数据对第二轮造成影响 int count = 0;//统计窗口中“有效字符串”的个数 left = i; //for(right = i; right <= (int)s.size() - len; right += len) //写成上面s.size() - len的形式一定要注意size()返回的类型是size_t //当size_t类型与int类型进行运算时,结果会类型转换出size_t类型 //如果此时s.size() - len为负数则会变成最大值,导致substr越界访问right //所以我们需要先将s.size()返回类型强转成int类型才能进行运算 for(right = i; right + len <= s.size(); right += len) { string str1 = s.substr(right, len); hash2[str1]++; //进窗口 if(hash2[str1] <= hash1[str1]) { count++; } if(right - left + 1 > len * m) //判断 { string str2 = s.substr(left, len); if(hash2[str2] <= hash1[str2]) { count--; } hash2[str2]--; //出窗口 left += len; } if(count == m) //更新结果 { ret.push_back(left); } } } return ret; } };

算法总结及流程解析:

16. 最小覆盖子串

题目链接:

76. 最小覆盖子串 - 力扣(LeetCode)

题目描述:

题目示例:

解法 (滑动窗口+哈希表):

算法思路:

      研究对象是连续的区间,因此可以尝试使用滑动窗口的思想来解决。

      如何判断当前窗口的所有字符是符合要求的呢?

  • 我们可以使用两个哈希表。其中一个将目标串的信息统计起来,另一个哈希表动态的维护窗口内字符串的信息。
  • 当动态哈希表中包含目标串中所有字符,并且对应的个数都不小于目标串的哈希表中各个字符的个数,那么当前的窗口就是一种可行的方案。
算法流程:

  1. 定义两个全局的哈希表:hash1用来记录子串的信息,hash2用来记录目标串 t 的信息;

  2. 实现一个接口函数,判断当前窗口是否满足要求:

    2.1 遍历两个哈希表中对应位置的元素

      2.1.1 如果 t 中某个字符的数量大于窗口中字符的数量,也就是 hash2 某个位置大于 hash1 。说明不匹配,返回 false。

      2.1.2 如果全部匹配,返回 true。

主函数中:

  1.先将 t 的信息放入 hash2 中;

  2.初始化一些变量:左右指针:left = 0,right = 0;目标子串的长度:len = INT_MAX;目标子串的起始位置:begin;(通过目标子串的起始位置和长度,我们就可以找到结果)

  3.当 right 小于字符串 s 的长度时,一直下列循环:

    3.1 将当前遍历到的元素扔进 hash1 中;

    3.2 检测当前窗口是否满足条件;

      3.2.1 如果满足条件:

                        判断当前窗口是否变小。如果变小:更新长度 len,以及字符串的起始位置 begin

                        判断完毕后,将左侧的元素滑出窗口,顺便更新到 hash1;

                        重复上述两个过程,直到窗口不满足条件;

    3.3 right++,遍历下一个元素;

  4. 判断 len 的长度是否等于 INT_MAX;

    4.1 如果相等,说明没有匹配,返回空串;

    4.2 如果不相等,说明匹配,返回 s 中从 retleft 位置往后 len 长度的字符串。

C++算法代码:

class Solution { public: string minWindow(string s, string t) { // //解法一:滑动窗口 + 哈希表(使用容器),count 标记“有效字符”的个数 // unordered_map<char, int> hash1; // for(auto c : t) // { // hash1[c]++; // } // int count = 0; int left = 0; int right = 0; // int n = t.size(); int min_len = s.size() + 1; int begin = -1; // string ret; // unordered_map<char, int> hash2; // for(right = 0; right < s.size(); right++) // { // hash2[s[right]]++; //进窗口 // if(hash2[s[right]] <= hash1[s[right]]) // { // count++; // } // while(hash2[s[left]] > hash1[s[left]]) //判断 // { // hash2[s[left]]--; //出窗口 // left++; // } // if(count == n) // { // if(min_len > right - left + 1) //更新结果 // { // min_len = right - left + 1; // begin = left; // } // } // } // if(begin != -1) // { // ret = s.substr(begin, min_len); // } // return ret; //优化:数组模拟实现哈希表,count 标记“有效字符”的种类 int hash1[128] = { 0 }; //统计字符串 t 中每个字符出现的频次 int kinds = 0; //统计“有效字符”有多少种 for(auto c : t) { if(hash1[c]++ == 0) { kinds++; } } int left = 0; int right = 0; int count = 0; int min_len = s.size() + 1; int begin = -1; string ret; int hash2[128] = { 0 }; for(right = 0; right < s.size(); right++) { hash2[s[right]]++; //进窗口 if(hash2[s[right]] == hash1[s[right]]) { count++; } while(count == kinds)//判断 { if(min_len > right - left + 1) //更新结果 { min_len = right - left + 1; begin = left; } if(hash2[s[left]] == hash1[s[left]]) { count--; } hash2[s[left]]--; //出窗口 left++; } } if(begin != -1) { ret = s.substr(begin, min_len); } return ret; } };

算法总结及流程解析:

结束语

       到此,15.串联所有单词的子串,16.最小覆盖子串 这两道算法题就讲解完了。《串联所有单词的子串》采用滑动窗口 + 哈希表方法,将单词视为字符处理,通过控制窗口步长和频次统计实现高效匹配;《最小覆盖子串》通过双哈希表动态维护目标串和窗口字符频次,优化版使用128位数组提升效率。希望大家能有所收获!

Read more

英伟达免费开源大参数模型 Nemotron 3 Super 全解析

英伟达免费开源大参数模型 Nemotron 3 Super 全解析

前言:本文兼顾技术深度与可读性,全面解析英伟达最新免费开源大参数模型 Nemotron 3 Super——从模型核心特性、实测表现,到与主流开源模型的横向对比,再到 OpenClaw 中的具体使用方法,全程聚焦“免费、开源、高性能”三大核心,帮开发者快速上手、高效应用,适合各类开发者、技术爱好者及相关从业者阅读参考。 一、模型全景介绍:英伟达“开源王炸”Nemotron 3 Super 在 AI 大模型赛道,英伟达不再满足于“卖铲子”(GPU 硬件),而是亲自下场“挖金子”——近期重磅推出的 Nemotron 3 Super,作为其史上最强开源权重模型,以 1280 亿总参数量(推理仅激活 120 亿)、100 万

【Seedance 2.0 安全合规红线指南】:飞书机器人集成中97%开发者忽略的5大隐私漏洞及零信任加固方案

第一章:Seedance 2.0 飞书机器人集成安全合规总览 Seedance 2.0 与飞书机器人的深度集成严格遵循《个人信息保护法》《数据安全法》及飞书开放平台《机器人接入安全规范 V3.2》,构建覆盖身份认证、数据传输、权限控制与审计追溯的全链路安全合规体系。所有机器人交互均默认启用双向 TLS 加密,敏感操作强制触发二次身份确认,并通过飞书「应用沙箱」机制实现运行环境隔离。 核心安全控制机制 * OAuth 2.0 授权范围最小化:仅申请 chat:read、user:read 和 bot:chat 必需权限 * Webhook 请求签名验证:飞书平台使用 SHA256_HMAC 签名,服务端须校验 X-Lark-Signature 头 * 敏感数据自动脱敏:用户手机号、

MIT室内场景识别数据集-15,571张图片 室内场景识别 机器人导航 智能建筑 深度学习 机器学习 语义理解 安防监控 虚拟现实`

MIT室内场景识别数据集-15,571张图片 室内场景识别 机器人导航 智能建筑 深度学习 机器学习 语义理解 安防监控 虚拟现实`

🏢 MIT室内场景识别数据集-15,571张图片-文章末添加wx领取数据集 * 📦 已发布目标检测数据集合集(持续更新) * 🏢 MIT室内场景识别数据集介绍 * 📌 数据集概览 * 包含类别 * 🎯 应用场景 * 🖼 数据样本展示 * 使用建议 * 🌟 数据集特色 * 📈 商业价值 * 🔗 技术标签 * YOLOv8 训练实战 * 📦 1. 环境配置 * 安装 YOLOv8 官方库 ultralytics * 📁 2. 数据准备 * 2.1 数据标注格式(YOLO) * 2.2 文件结构示例 * 2.3 创建 data.yaml 配置文件 * 🚀 3. 模型训练 * 关键参数补充说明: * 📈 4. 模型验证与测试 * 4.1 验证模型性能 * 关键参数详解 * 常用可选参数 * 典型输出指标 * 4.2 推理测试图像

AR 定位技术深度解析:从 GPS 到视觉 SLAM 的轻量化实现

AR 定位技术深度解析:从 GPS 到视觉 SLAM 的轻量化实现

⭐️个人主页:秋邱-ZEEKLOG博客 📚所属栏目:python 开篇:定位是 AR 的 “空间地基”,解决 “虚拟内容放哪里” 的核心问题 AR 技术的核心是 “虚实融合”,而定位技术则是实现这一融合的基础 —— 如果无法精准确定手机在真实空间中的位置和姿态,虚拟内容就会出现 “漂移、悬浮、穿透” 等问题,严重影响用户体验。 实际开发中,我们常面临这样的困境:户外场景用 GPS 定位误差太大(5-10 米),室内场景 GPS 信号弱甚至失效,而商用 SLAM 方案(如 ARKit/ARCore 的视觉 SLAM)虽然精度高,但底层逻辑黑盒化,难以自定义优化。本期我们将彻底拆解 AR 定位的核心技术,对比 GPS、BLE(