题目描述:
给定一个字符串,请找出其中无重复字符的最长子字符串。
样例:
例如,在”abcabcbb”中,其无重复字符的最长子字符串是”abc”,其长度为 3。
对于,”bbbbb”,其无重复字符的最长子字符串为”b”,长度为1。
思路讲解:我一开始的想法是利用set存储字符,然后一旦找到重复的元素,我们就将其对应的元素在主串中的位置找出来,然后从这个地方接着进行hash查找,结果时间不够,经过分析是因为我每次都需要先将set表清除,然后将后面的添加进去,这是增加很多时间,进而导致运行到92%时提示超时。后面我就思考能不能不要增加set表重复的清除和添加,后面想到重复的原因就是需要找到重复元素的位置,那么我们直接将每一个字符所对应的位置,也一起存储进去,这样就可以直接找到重复元素的位置,这样我们下次查找的时候就只需要判断查找的位置是否比上一次的起始位置要大,要大的话,我们就可以说明是找到重复元素,如果小于的话,则没有找到,这样就节省了很多时间。
代码详解:
class Solution {
public:
/*
* @param s: a string
* @return: an integer
*/
int lengthOfLongestSubstring(string &s) {
// write your code here
map<char,int>mp;
int len=s.length();
if(len<=1){
return len;
}
int start=0;//记录无重复子串的起始位置
int max=0;//记录最长的字符串长度
for(int i=0;i<len;i++){
if(mp.empty()){
mp[s[i]]=i+1;
}else{
if(mp.find(s[i])==mp.end()){
mp[s[i]]=i+1;
}else if(mp.find(s[i])!=mp.end()&&mp[s[i]]>start){
//cout<<"次数是"<<endl;
//cout<<i<<" "<<s[i]<<" "<<start<<endl;
int mp_size=i-start;
start=mp[s[i]];
if(mp_size>max){
max=mp_size;
}
mp[s[i]]=i+1;
//printset(mp);
//cout<<start<<" "<<max<<endl;
}else{
mp[s[i]]=i+1;
}
}
}
//cout<<start<<endl;
int tmp=len-start;
return max>tmp?max:tmp;
}
void printset(map<char,int>res){
map<char,int>::iterator iter;
for(iter=res.begin();iter!=res.end();iter++){
cout<<iter->first<<" "<<iter->second<<endl;
}
cout<<"----------------------"<<endl;
}
};