题目:单词匹配
给定两个字符串S和T。要求设计一个复杂度为的算法,在S串当中找到一个子串,能够包含T串当中的所有字符。要求返回合法且长度最小的窗口的内容。
示例
Input: S = "ADOBECODEBANC", T = "ABC" Output: "BANC"
思路
要统计Target串中字母的个数,一要考虑target串的长度,二要考虑target串中每个字符出现的次数。
- 遍历一遍target串,用map保存每个字符出现的次数;
- 对于S中的每个遍历到的字母,都在 HashMap 中的映射值减1,如果减1后的映射值仍大于等于0,说明当前遍历到的字母是T串中的字母,使用一个计数器 cnt,使其自增1。
- 当 cnt 和T串字母个数相等时,说明此时的窗口已经包含了T串中的所有字母,此时更新一个 minLen 和结果 res
- 开始收缩左边界,由于遍历的时候,对映射值减了1,所以此时去除字母的时候,就要把减去的1加回来,此时如果加1后的值大于0了,说明此时少了一个T中的字母,那么 cnt 值就要减1了,然后移动左边界 left。
解法
class Solution {
public:
string minWindow(string s, string t) {
string res = "";
unordered_map<char, int> letterCnt;
int left = 0, cnt = 0, minLen = INT_MAX;
for (char c : t) ++letterCnt[c];
for (int i = 0; i < s.size(); ++i) {
if (--letterCnt[s[i]] >= 0) ++cnt;
while (cnt == t.size()) {
if (minLen > i - left + 1) {
minLen = i - left + 1;
res = s.substr(left, minLen);
}
if (++letterCnt[s[left]] > 0) --cnt;
++left;
}
}
return res;
}
};
题目:求无重复的最长子串
示例
Input: S = "pwwabcdefgkew" Output: 9
思路:set + 前后指针(下标)
左下标记录第一个不重复的字符位置start,用一个set来记录扫描过的字符串,如果遇见相同的字符串,下标为i:
- 保存当前的子串长度 maxLen = (i - 1) - start + 1;
- 左下标前移到第一次出现的位置 + 1;
- 继续遍历子串,遇到重复的字符,更新maxLen = max(maxLen, (i - 1) - start + 1);
解法
int getNoRepeatdLongestSubString(string s) {
int maxLen = 0;
set<char> st;
int start = 0;
for (int i = 0; i < s.length(); i++) {
if (st.count(s[i]) == 1 ) {
maxLen = max((i - 1 - start + 1), maxLen);
for ( ; start < i; start++) {
if (s[start] == s[i]) { start++; break;}
}
} else {
st.insert(s[i]);
}
}
return maxLen;
}
一个小的优化:使用map记录第一次出现的下标,下一次继续扫描时,左指针只需移到mp[s[i]] + 1
int getNoneRepeatdLongestString(string s) {
if (s.length() == 0) return 0;
map<char, int> mp;
int maxLen = 0, start = 0;
for (int i = 0; i < s.length(); i++) {
if (mp.find(s[i]) != mp.end()) {
maxLen = max(abs(i - 1 - start + 1), maxLen);
start = mp[s[i]] + 1;
}
mp[s[i]] = i;
}
return maxLen;
}