题意理解
给定一个字符串,求最小无重复子串。
问题分析
滑动窗口
0923:本质上是一个动规的思想,从左向右挨个字符开头,求最长的无重复字符子串。
其他
算法思路要动笔,画盒图比较好,不能直接强记。
算法再分两层:一层是思想,归结到算法结构;一层是细节实现,归结到变量设置,变量的含义。看本题:思想是动规,从左到右每个字符开头,向后遍历得到最长子串。细节层面转化为实现两个指针,加一个字典或集合,两个指针指向子串的开头和结尾,字典和集合表征不重复。
int lengthOfLongestSubstring(string s) {
if(s.size()==0) return 0;
int len=s.size();
set<int> my_set{}; //保存滑动窗口字符集合,所求最小无重复子字符串
int max_len=INT_MIN;
int left=0, right=0; //滑动窗口左右下标
while(left<len && right < len) { //遍历字符串
char ch=s[right];
cout << ch << endl;
if(my_set.count(ch)) { //如果当前字符存在在滑动窗口
//cout << "exist" << endl;
my_set.erase(s[left]); //删窗口头元素
left++; //缩小窗口
}
else { //不在
//cout << "no exist" << endl;
my_set.insert(ch); //插入
right++; //扩大窗口
int len_set=my_set.size(); //窗口大小
//cout << len_set << endl;
max_len=max(max_len, len_set);
}
}
return max_len;
}
链接
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int cnt = s.size();
if (cnt <= 1) return cnt;
int low = 0, high = 0;
int max_len = INT_MIN;
unordered_map<char, int> my_dict;
for (int low = 0; low < cnt; low ++) {
//cout << "low " << low << endl;
if (low != 0) {
my_dict.erase(s[low-1]); //删掉前一个
}
while (high < cnt) {
//cout << s[high] << endl;
if (my_dict.count(s[high])) {
break;
}
else {
my_dict[s[high]]++;
}
high ++;
}
//cout << "high:" << high << endl;
int cur_len = high - low;
if (cur_len > max_len) max_len = cur_len;
}
return max_len;
}
};