!!!题解 | 最小覆盖子串 优化非常循序渐进 注意ascii码值 使用hash就是无序map
最小覆盖子串
https://www.nowcoder.com/practice/c466d480d20c4c7c9d322d12ca7955ac
数字:0-9,对应十进制值48-57。
大写字母:A-Z,对应十进制值65-90。
小写字母:a-z,对应十进制值97-122。
标准 ASCII 使用7位编码,扩展 ASCII 使用8位编码,增加了128个字符,支持更多符号和语言字符。然而,扩展 ASCII 并非国际标准,不同国家和系统的实现可能有所不同。
#include <vector>
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param S string字符串
* @param T string字符串
* @return string字符串
*/
string minWindow(string S, string T) {
// write code here
//这个还不是KMP算法 只是这个子串包含这些元素就行 而不要求顺序、是否连续
//没啥好思路
//注意 ascii码 1B 但只有126个有效 7位
//主要是判断这个子串是否满足要求 可以用无序map key为字符 值为出现的次数
//若找到了 记录长度 移动左指针 直到再次符合条件 然后更新长度值
/*
官方的代码还可以优化 比如不用无序哈希 使用数组 因为只包含大写和小写字母。所以用值表示1下标
二是判断左边界增加后 是否还满足条件 可以使用对于t不出现 s出现以及s、t都出现的字符做不同层次的处理。(也就是值的最大边界不同
移除一个左边的字符后 判断它是否是在t中 可以为它的下标的值--,看他是否还大于0,而他如果在t中 就小于0了。
*/
int size=S.size();
int ansleft=-1;
int ansright=size;//J记录的是下标
vector<int> sign(128,0);//模仿hash表 ascii码有效值0-127
int kinds=0;
int sizet=T.size();
for(int i=0;i<sizet;i++){
if(sign[T[i]]==0)kinds++;
sign[T[i]]--;//这是要还债的 出现在t里的所有元素以及次数
}
int getkind=0;
int left=0;int right=0;
for(int i=0;i<size;i++){//这里i就等于right,right可以不用要
char cur=S[i];
sign[cur]++;
if(sign[cur]==0)getkind++;
while(getkind==kinds){//这里就有了一个限制条件了 不用那个break了
if((i-left)<(ansright-ansleft)){
ansleft=left;
ansright=i;
}
//left++;
if((sign[S[left]])==0){
getkind--;
}
sign[S[left]]--;//这一句必须写在条件分支外面 因为t中有些字符出现次数不止一次。while的条件决定getkind是最重要的
left++;
}
}
if(ansleft==-1)return "";
return S.substr(ansleft,ansright-ansleft+1);
}
};
查看15道真题和解析