1.题目要求
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.
2.分析
读懂题目之后,脑海中出现的第一个解决方法就是遍历字符串s,当某个字符在比它靠前的字符串s1中出现过时,按照如下方法处理:
假设初始字符串s,两个下标i,j,从头开始扫描,当扫描到j+1时,s[j+1]属于s[0……j],注意s[0……j]中的字符都不相同。假设s[i]=s[j+1],result = j-0+1;接下来说明如果存在满足条件并且比result大的子串,一定是从s[i+1]开始往后的子串。
因为s[i]=s[j+1],因此,任意一个以s[1……i]一个字符开始的子串,并且满足题目要求的串都终止与s[j],其长度必然小于result。如果想要找到一长度大于result并且满足要求的子串,必然要从s[i+1]开始往后寻找。
代码如下:
class Solution { public: int lengthOfLongestSubstring(string s) { int res=0,i=0,j=0; int length = s.length(); if (0 == length) { return 0; } set<char> mySet; mySet.clear(); while (j<length) { if(mySet.find(s[j]) == mySet.end()) { mySet.insert(s[j]); j++; } else { if(j-i > res)res = j-i; mySet.clear(); i++; j=i; } } if(j-i > res)res = j-i; return res; } };
提交答案。Time Limit Exceeded。悲伤啊。
重新判断这个算法,我们会发现,算法会产生回溯,也就是j被赋值为i时,导致回溯,算法时间复杂度最坏情况是O(2n)。因此我们需要想办法避免这个多余的开销,保证j在前进的方向永不回头。
在上述方法中,当发现s[i]=s[j+1]时,我们是采取把下标j往回移动,我们可以换一个角度,将start往后移动到i+1处,这里需要注意啊,start在移动的时候,需要将s[start]从set中剔除。这个算法需要保存好之前出现的字符的下标
代码如下:
1 class Solution { 2 public: 3 int lengthOfLongestSubstring(string s) { 4 int res=0; 5 int length = s.length(); 6 if (0 == length) 7 { 8 return 0; 9 } 10 int i=0,j=1; 11 int index[256]; 12 memset(index,-1,sizeof(index)); 13 index[s[0]]=0; 14 while (i<j&&j<length)//"abcabcbb" 15 { 16 if(-1 == index[s[j]]) 17 { 18 index[s[j]]=j; 19 20 } 21 else 22 { 23 if(j-i>res)res = j-i; 24 while(true) 25 { 26 if (s[i]!=s[j]) 27 { 28 index[s[i]]=-1; 29 i++; 30 }else 31 break; 32 33 } 34 i++; 35 } 36 j++; 37 38 39 } 40 if(j-i>res)res = j-i; 41 return res; 42 } 43 };
提交代码,Accepted。