Leetcode30. 串联所有单词的子串
利用substr函数截取出来的s中截取出一段一段的单词,然后和words中比较是否相等。
hash1
用来存储words中单词出现的次数- left right指针每次移动的步数为
wordLen= words[i].size()
,也就是单词的长度- 边界
right + wordLen<= words.size()
hash2
维护窗口内单词出现次数if(hash1.count(in) && hash2[in] <= hash1[in]) count++;
if(hash1.count(out) && hash2[out] <= hash1[out]) count--;
代码
class Solution
{
public:
vector<int> findSubstring(string s, vector<string>& words)
{
vector<int> res;
unordered_map<string, int> hash1;//保存words里面单词出现的次数
for(auto i : words) hash1[i]++;
int wordLen = words[0].size(), n = words.size();
for(int i = 0; i < wordLen; i++)
{
unordered_map<string, int> hash2;//维护窗口中单词出现的次数
for(int left = i, right = i, count = 0; right + wordLen <= s.size(); right += wordLen)
{
//进窗口 + 维护count
string in = s.substr(right, wordLen);
hash2[in]++;
if(hash1.count(in) && hash2[in] <= hash1[in]) count++;
if(right - left + 1 > wordLen * n)//判断
{
//出窗口 + 维护count
string out = s.substr(left, wordLen);
if(hash1.count(out) && hash2[out] <= hash1[out]) count--;
hash2[out]--;
left += wordLen;
}
//更新结果
if(n == count) res.push_back(left);
}
}
return res;
}
};
时间复杂度O(N*M)
Leetcode76. 最小覆盖子串
- left = 0, right = 0;
- 进窗口
hash2[in]++
- 判断
check(left, right)
-> 出窗口hash2[out]--
- 更新结果(位置每一题都不同,本题在判断后)
利用count来统计有效字符的种类(在check判断的时候,用来优化)
1. 进窗口之前 当hash2[in] == hash1[in] count++;
2. 出窗口之后 当hash2[out] ==hash1[out] count - - ;
3. 判断时 count == hash1.size();
代码
class Solution
{
public:
string minWindow(string s, string t)
{
int hash1[128] = {0};//统计t中每个字母出现的次数
int kinds = 0;//统计有效字母的种类
for(auto i : t) if(hash1[i]++ == 0) kinds++;
int hash2[128] = {0};//统计窗口内每个字母出现的次数
int res = INT_MAX;
int begin = -1;
for(int left = 0, right = 0, count = 0; right < s.size(); right++)
{
char in = s[right];
if(++hash2[in] == hash1[in]) count++;//进窗口+维护count
while(count == kinds)//判断
{
if(right - left + 1 < res)//更新结果
{
res = right - left + 1;
begin = left;
}
char out = s[left++];
if(hash2[out]-- == hash1[out]) count--;//出窗口+维护count
}
}
return begin == -1? "" : s.substr(begin, res);
}
};