问题描述:
Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.
开始理解题目时有问题,受到例子的影响,以为是找到"abc"这样重复过的字符串(“abc”重复了两次),没有理解without repeating characters 是什么意思,思路是从字符本身开始,依次减少一个字符(最左边和最右边),得到一个新字符,判断是否在原字符串中出现过两次或者以上。。。。写在这里作为警示,做题目前一定先明白题目的意思。
此题的意思是找到一个长度最长子字符串,子字符串本身内部没有重复的字符。以"abcda"为例子,读入一个字符时,判断在前面有没有出现,如果没有出现("b"),继续读下一个字符,长度加一,如果有出现(第二个"a"),子字符串的长度不能在增加了,以第二个"a"为起点继续读后面的数据,当然这是看了大牛的答案才得到的。答案如下:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
vector<int> table(256,-1);
int start=-1;
int maxLength=0;
for(int i=0;i<s.length();i++)
{
if(table[s[i]] >= start )
start=table[s[i]];
table[s[i]]=i;
maxLength=max(maxLength,i-start);
}
return maxLength;
}
};
其中要注意的地方:
1. 用start(或者说表格、字典)来记录最长无重复子串的前一个位置
2. 用table记录字符最近一次出现的位置,读第i个字符,如果最近一次出现的位置在start后,出现重复,更新start位置
3. "abcabcbb"中符合要求的子字符串不仅仅只有"abc","bca","cab"都符合要求。
4. 如果要找到全部的符合要求的字符串,我们需要记录maxLength和i-start相同时对应的子字符串。如果i-start > maxLength,则找到更长的字符串,清空记录,重新记
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int table[256]; //int table[256]={-1};只有第一个元素为-1 后序为 0 memset操作是一个字节 对于int也不适用
for(auto & i:table)
i=-1;
set<string> strs;
int currMaxLeng=0;
int start=-1;
int maxLength=0;
for(int i=0;i<s.length();i++)
{
if(table[s[i]] >= start )
start=table[s[i]];
table[s[i]]=i;
maxLength=max(currMaxLeng,i-start);
if(currMaxLeng == i-start)
{
strs.insert(s.substr(start+1,i-start));//start标记的是子串前一个位置 start+1
}else if(i-start > currMaxLeng)
{
strs.clear();
currMaxLeng=maxLength;
strs.insert(s.substr(start+1,i-start));
}
}
for(auto i: strs)
{
cout<<i<<endl;
}
return maxLength;
}
};