题目大意:求出一给定字符串的最长子串,要求子串中的字符无重复。子串与子序列的区别是:子串必须要求是相连着的字符组成,而子序列则允许字符可间断。
题目分析:
用num[i]表示以字符s[i]结尾的最长子串,我们只要将指针从i往前扫描,发现有重复的字符则停止计数,得到的数值即以s[i]结尾的最长子串的长度。时间复杂度为O(n^2)
代码展示:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int len = s.length();
bool visit[256];
memset(visit,0,sizeof(visit));
int count = 0;
int max = 0;
for(int i=0;i<len;i++){
for(int j=i;j>=0;j--){
if(!visit[s[j]]){
count++;
visit[s[j]] = 1;
}
else
break;
}
if(count>max)
max = count;
memset(visit,0,sizeof(visit));
count = 0;
}
return max;
}
};
第二种解法是,最长子串为s[start,...,i],返回该子串的长度即可。关键是,在一遍循环中,start和i是动态变化的。举例来说,s="abcabcbb".
首先,start指向为-1位置,i为0位置,pos['a']=0, 返回长度i-start=1;
然后i=1, 没出现重复,start没变,pos['b']=1, 返回i-start=2;
然后i=2, 没出现重复,start没变,pos['c']=2, 返回i-start=3;
然后i=3, 出现了重复, start后移,start = pos['a'] = 0, 更新pos['a'] = 4,返回i-start=3 ……
这里start为什么要后移? 因为子串要求是无重复的,要是start不后移的话,必然会是abca,出现了重复的a,故一旦出现重复,就要后移start,后移到第一次出现a的位置。
代码展示:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int maxlen = 0;
int pos[256];
memset(pos,-1,sizeof(pos));
int start = -1;
for(int i=0;i<s.length();i++){
if(pos[s[i]]>start)
start = pos[s[i]];
pos[s[i]] = i;
maxlen = max(maxlen,i-start);
}
return maxlen;
}
};