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

输入:s = "ADOBECODEBANC", t = "ABC"

输出:"BANC"

解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

用暴力解法的时间复杂度是O(n^2),我这里使用滑动窗口法实现的时间复杂度是O(n)

核心思路:滑动窗口(双指针) 结合 哈希表。通过维护一个动态窗口(由左右指针界定),逐步扩大和缩小窗口以寻找满足条件的最小子串。

  1. 统计目标字符需求:用哈希表 tmap 记录 t 中每个字符的出现次数(键为字符,值为次数),并记录 t 中不同字符的种类数。
  2. 维护窗口字符统计:用哈希表 smap 记录当前窗口中每个字符的出现次数。
  3. 动态调整窗口:

    移动右指针扩大窗口,直到窗口包含 t 中所有字符(且数量满足需求)。

    当窗口满足条件时,移动左指针缩小窗口,尝试在保持条件的前提下找到更小的子串。
  4. 判断窗口有效性:用变量 valid 记录窗口中满足要求的字符种类数,当 valid 等于 t 的字符种类数时,窗口有效。
class Solution {
public String minWindow(String s, String t) { Map<Character, Integer> smap = new HashMap<>(); //当前窗口
Map<Character, Integer> tmap = new HashMap<>();
int left = 0, right = 0; // 左右指针
int valid = 0; // 满足频率条件的字符数量(统计有效字符),比如当smap中A的数量达到3个时,valid才会把A当做有效字符,valid加一
int start = 0, minLen = Integer.MAX_VALUE; // 最小子串的起始位置和长度
int slength = s.length(); // 处理边界情况
if (s == null || t == null || s.length() == 0 || t.length() == 0 || s.length() < t.length()) {
return "";
} // 统计t中每个字符出现的次数
for (char c : t.toCharArray()) {
tmap.put(c, tmap.getOrDefault(c, 0) + 1);
}
int tmap_size = tmap.size(); // t中字符种类数 /**
遍历s字符串
*/
while (right < slength) {
char c = s.charAt(right); // 判断是不是目标字符
if (tmap.containsKey(c)) {
smap.put(c, smap.getOrDefault(c, 0) + 1); //更新目标字符的频率
if (smap.get(c).intValue() == tmap.get(c).intValue()) { // 如果频率相同了,成为有效字符,加入字符计数器
valid++;
}
} /** 判断是不是子串。
是子串则要更新长度,然后缩小窗口(用左指针遍历当前窗口)
*/
while (valid == tmap_size) { //有效字符数量与t相等
// 如果当前子串长度更小,则更新最小子串索引和长度
if (right - left+1 < minLen) {
start = left;
minLen = right - left+1;
} /** 逐步缩小窗口,移除左指针的字符
*/
char d = s.charAt(left);
// 如果左指针元素是有效元素,则在smap中移除d字符
if (tmap.containsKey(d)) {
smap.put(d, smap.get(d) - 1); // 移除字符 d 后,判断是否要更新有效字符数。比较smap与tmap中的d数量,如果d字符数量变少了,说明d是有效字符,所以移除d后,有效值需要减 1。
if(smap.get(d).intValue() < tmap.get(d).intValue() ){
valid--;
}
} left++;
}
right++;
} return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen); // 如果没有找到最小字符串则返回空字符串。否则返回 从索引start到索引start+minLen(不包含!!)
}
}

时间复杂度O(n)查找最小覆盖子串的更多相关文章

  1. 【1】【leetcode-76】 最小覆盖子串

     最小覆盖子串(hard) (不会) 给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串. 示例: 输入: S = "ADOBECODEBANC", ...

  2. [LeetCode] 76. 最小覆盖子串 ☆☆☆☆☆(滑动窗口)

    https://leetcode-cn.com/problems/minimum-window-substring/solution/hua-dong-chuang-kou-suan-fa-tong- ...

  3. [LeetCode]438. 找到字符串中所有字母异位词、76. 最小覆盖子串(滑动窗口解决子串问题系列)

    题目438. 找到字符串中所有字母异位词 给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引. 说明: 字母异位词指字母相同,但排列不同的字符 ...

  4. POJ2185Milking Grid(最小覆盖子串 + 二维KMP)

    题意: 一个r*c的矩形,求一个子矩形通过平移复制能覆盖整个矩形 关于一个字符串的最小覆盖子串可以看这里http://blog.csdn.net/fjsd155/article/details/686 ...

  5. KMP算法 - 求最小覆盖子串

    KMP与最小覆盖子串 最小覆盖子串:对于某个字符串s,它的最小覆盖子串指的是长度最小的子串p,p满足通过自身的多次连接得到q,最后能够使s成为q的子串. 比如: 对于s="abcab&quo ...

  6. Milking Grid POJ - 2185 || 最小覆盖子串

    Milking Grid POJ - 2185 最小覆盖子串: 最小覆盖子串(串尾多一小段时,用前缀覆盖)长度为n-next[n](n-pre[n]),n为串长. 当n%(n-next[n])==0时 ...

  7. Leetcode 76.最小覆盖子串

    最小覆盖子串 给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串. 示例: 输入: S = "ADOBECODEBANC", T = "A ...

  8. 【t011】最小覆盖子串

    Time Limit: 1 second Memory Limit: 32 MB [问题描述] 给定一个含有N个元素的序列A,你的任务就是求出序列A的最小覆盖子串的长度. 本题中的一些定义: 串S,是 ...

  9. Java实现 LeetCode 76 最小覆盖子串

    76. 最小覆盖子串 给你一个字符串 S.一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串. 示例: 输入: S = "ADOBECODEBANC", T = ...

  10. 【LeetCode】76. 最小覆盖子串

    76. 最小覆盖子串 知识点:字符串:滑动窗口 题目描述 给你一个字符串 s .一个字符串 t .返回 s 中涵盖 t 所有字符的最小子串.如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ...

随机推荐

  1. Axure RP中后台管理系统通用原型模板元件库

    Axure RP中后台管理系统通用原型方案 v2是一套通用型的中后台信息系统原型方案,可以快速扩展并输出标准美观的中后台产品原型,极大的提升输出效率和节省协作成本.方案中提供了几十套不同风格和结构的系 ...

  2. C#窗体磁吸屏幕的两种实现方案 - 开源研究系列文章

    以前在大学的时候模仿Winamp的磁吸效果编写过一个类库,用于在应用中多个窗体的相互磁吸效果.因为此效果应用不多,但是窗体磁吸屏幕边缘的效果倒是比较实用,于是就用C#来实现窗体磁吸屏幕边缘的代码,这里 ...

  3. wireshark 抓包查看包得明文消息

    转载注明出处: 最近在进行一些网络消息得定位,发现可以用wireshark查看网络包得消息内容,特此记录 需要注意得是,需要将wireshark更新到最新得版本,如果是老版本有可能不支持. 使用tcp ...

  4. Git 查看 tag 标签详解

    摘要:介绍git中tag标签的使用方法,包括创建标签.提交标签.查询标签和删除标签等. 我们拿到一个即将投产的标签后,需要确认标签是否打在了正确的分支,故需要查看标签的详情信息,保证顺利上线.基于此背 ...

  5. yoga14c2024(ultra7-155H)使用雷电4转接oculink外接RTX4070Ti Super跑分

    yoga14c2024(ultra7-155H)使用雷电4转接oculink外接RTX4070Ti Super跑分 自媒体跑分 内屏 \[损耗=1-16731/24723\approx32.3\%\n ...

  6. Linux下安装并配置VSCode(Visual Studio Code)

    众所周知,微软官方推出的开源编辑器VSCode轻量.易用.美观(微软没有给我广告费哈_),在程序员界享有盛誉,今天就带着大家在Linux下快速下载并使用VCode编辑器. 1.下载VSCode包 下载 ...

  7. 2023电赛E题代码

    openmv: import sensor, image, time from pyb import LED, UART #import lcd import json, ustruct class ...

  8. AWS学习笔记之Lambda执行权限

    最近在网上看到一道关于AWS Lambda的题,十分有意思: A developer has an application that uses an AWS Lambda function to up ...

  9. 详细剖析|袋鼠云数栈前端框架Antd 3.x 升级 4.x 的踩坑之路

    袋鼠云数栈从2016年发布第⼀个版本开始,就始终坚持着以技术为核⼼.安全为底线.提效为⽬标.中台为战略的思想,坚定不移地⾛国产化信创路线,不断推进产品功能迭代.技术创新.服务细化和性能升级. 在数栈过 ...

  10. Windows命令行shutdown命令和快速启动之间的一点坑

    Hybrid shutdown 自Win8.1开始,在休眠和完全关闭之外,多出一个"混合关闭(hybird shutdown)"的状态.在"控制面板\硬件和声音\电源选项 ...