1.题目描述:求出一个字符串中最长的无重复字符的字符串长度
2.方法一:hash表+暴力解法
依次求出以每个字符打头的无重复的字符串的最大长度。通过hash表可以在o(1)时间内找到新加入的字符是否重复,不重复则加入hash表中,依次遍历后续字符,直到出现重复字符,则获得当前打头字符的最大不重复子串长度。判断是否需要更新maxlen。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int maxlen=0;
for(int i=0;i<s.size();i++){
unordered_map<char,int> map_ch;//必须放在循环内!!!!!
int cnt=0,j=i;
for(;j<s.size();j++){
if(map_ch.find(s[j])!=map_ch.end()){
break;
}
map_ch[s[j]]=j;
}
cnt=j-i;
maxlen=cnt>maxlen?cnt:maxlen;//易错:不能将这行代码放进内层循环内,否则最后一次结果
//无法更新,如,只有一个字符时,则立马出错
}
return maxlen;
}
};
- 优点:思路清晰简单;
- 缺点:时间复杂度为O(n^2)
3.方法二:hash表+加速暴力解法
方法一思路清晰简单,但是存在大量无用的重复计算,实际上可以通过以前的比较结果来加速后面的判断。实现o(n)的时间复杂度。准备两个下标i,j分别表示无重复子串的开头和结尾。
结论1:遍历后续字符过程中发现前面有重复字符。若前面的重复字符出现在i之前,则下一步搜索从i+1后开始且i开头的子串必然不会是最长子串。(前面必然有比它长的),所以当前面重复字符出现在i之前时,更新下标后接着遍历后续字符
结论2:遍历后续字符过程中发现前面有重复字符。若前面重复字符出现在i或i之后,则下一步搜索从前面重复字符之后开始且i开头的子串可能会是最长子串。之后记得还是要更新下标。
利用结论2可实现:加速1:可以排除从i到前面重复字符之间字符开头能够找到最长不重复子串的可能性,加速i
加速2:从k+1到j之间字符必然无重复字符,前面已经搜索过,不必重复计算,j++即可,加速j。
只要出现重复字符,无论在前在后,都要更新下标。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int maxlen=0,cnt=0,i=0,j=0,len=0;
unordered_map<char,int> hash;
len=s.size();
while(i<len){//以每个字符打头
while(j<len){//以i+1之后每个字符结尾
if(hash.find(s[j])!=hash.end()&& hash[s[j]]>=i){
break;
}
hash[s[j]]=j;//此时要更新下标
j++;
}
cnt=j-i;
maxlen=max(maxlen,cnt);
if(j<len){
i=hash[s[j]]+1;//加速1
hash[s[j]]=j;//更新重复字符,此处务必注意,要更新最新出现的重复字符,否则当出现
//重复字符时可能会误判断成i之前,那么就会出错
j++;//加速2,不重复计算
}else{
break;
}
}
return maxlen;
}
};
3.方法三:数组+加速暴力解法
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int maxlen=0,i=0,j=0,len=0;
int exist[256];
memset(exist, 0xff, sizeof(exist));//!!!!!切记易错
len=s.size();
while(i<len){//以每个字符打头
while(j<len){//以i+1之后每个字符结尾
if(exist[s[j]]!=-1 && exist[s[j]]>=i){
break;
}
exist[s[j]] = j;
j++;
}
maxlen=max(maxlen,j-i);
if(j<len){
i = exist[s[j]] + 1;
exist[s[j]] = j;
j++;
}else{
break;
}
}
return maxlen;
}
};
类似的方法
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int maxlen = 0, i = 0, j = 0, len = 0;
int exist[256];
memset(exist, 0xff, sizeof(exist));//!!!!!切记易错
len = s.size();
while (j<len){
if (exist[s[j]] != -1){
maxlen = maxlen>(j - i) ? maxlen:(j - i);
while (i <= exist[s[j]]){
exist[s[i]] = -1;
i++;
}
}
exist[s[j]] = j;
j++;
}
maxlen = maxlen>(j - i) ? maxlen:(j - i);//最后必须加此一句,如若只有一个字符a时,
//无则出错
return maxlen;
}
};
4.方法四:动态规划