一、介绍
1.题目描述
题目链接:https://leetcode-cn.com/problems/minimum-window-substring/
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
- 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
- 如果 s 中存在这样的子串,我们保证它是唯一的答案。
2.测试样例
"ADOBECODEBANC"
"ABC"
# "BANC"
"a"
"a"
# "a"
"a"
"aa"
# ""
二、题解_滑动窗口🟡
原理:
1、起始时左右指针均为0,用 start 和 len 分别记录解的起始位置和长度【start=0,len=INT_MAX】
2、右指针向右移动,直到 左右指针之间的字符串包含 t 中全部字符【即可作为一个解】
3、若该解的长度 < len ,更新 start 和 len
4、移动左指针,直到 左右指针之间的字符串 不再 包含 t 中全部字符
5、循环234步骤,直到 r > 字符串 s 的长度
- 用 count 记录需要的字符总个数,即需求个数
- 用 map数组 记录所需的各个字符个数
- 用 flag数组 记录该字符是否在 t 中
- 每次左右指针移动,都对map 进行更新,map[i] < 0代表过剩,>0代表有需求
- 借助字母的ASCⅡ码来记录,值最多差58
class Solution {
public:
string minWindow(string s, string t) {
if(s==t||t=="") return t;
if(s.length()<t.length()) return "";
// map记录t中各元素及个数,map[i]>0代表该字母有需求
int map[58];
// 标记t中是否有该元素
int flag[58];
for(int i=0;i<58;i++){
map[i]=0;flag[i]=0;
}
for(int i=0;i<t.length();i++){
map[t[i]-'A']++;
flag[t[i]-'A']=1;
}
int n=s.length();
// 双指针初始均为0,count记录t的字母个数
int l=0,r=0,count=t.length();
// 记录解的起始坐标和长度
int start=0,len=INT_MAX;
while(r<n){
// 当有需求的字母出现时,count--
if(map[s[r]-'A']>0) count--;
// 更新map
map[s[r]-'A']--;
// 当字符串已经包含t的全部内容(即需求=0),移动左指针,直到不满足条件
while(count==0){
if(r-l+1<len){
start=l;
len=r-l+1;
}
// map[i]<0代表该字母过剩
// 如果左指针当前指向的字母在t中,且不过剩,需求个数增加
if(flag[s[l]-'A']==1&&map[s[l]-'A']>=0){
count++;
}
// 更新map
map[s[l]-'A']++;
l++;
}
// 移动右指针
r++;
}
// 如果无解,返回空
if(len>n)return "";
return s.substr(start,len);
}
};

本文介绍了如何使用滑动窗口算法解决LeetCode上的《最小覆盖子串》问题。通过设置左右指针并维护一个需求字符计数器,逐步移动指针找到包含目标字符串所有字符的最小子串。在移动过程中更新字符计数,并适时移动左指针以缩短子串长度。算法详细步骤和代码实现使得问题解决过程清晰易懂。
7305

被折叠的 条评论
为什么被折叠?



