3、无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
解题思路:
假设字符串为:abcdefghijk
1、最简单的,用暴力搜索法:遍历整个字符串,列举出所有的组合[ab、abc、abcd、...abcdefghijk]、
[bc、bcd、...bcdefghijk],遍历列举所有的组合,时间复杂度是O(N^2)。
再判断每个组合,不含重复字符的最长子串的长度,需要遍历该组合,时间复杂度是O(N)。
所以,暴力搜索法的总时间复杂度是O(N^3),差不多是会被面试官直接打死的效率。
2、利用动态规划的思路来处理:
我们记f(k)是已求解出的第k个字符,不含有重复字符的最长长度。
那么取出第k+1个字符,计算该字符上次出现的位置与当前位置的距离差,记为d。
a:如果字符从未出现过或d>f(k),则表示该字符没有出现在f(k)中,那么第f(k+1)=f(k)+1。
b:如果d<=f(k),那么k+1字符,出现在f(k)中,则此时f(k+1)=d。
举例来说就是:
a:对于字符串abcgeg,第一个字符g对应的f(g)=4,接下来取出字符e,字符e之前没有出现过,所以f(e)=f(g)+1=5。
b:接着取出第二个字符g:因为g之前出现过了,那么计算2个字符g的距离差d=2,所以第二个f(g)=2。
源码:
int lengthOfLongestSubstring(string s) {
int curLength = 0;
int maxLength = 0;
int *prePos = new int[128]; // 记录128个字符,上次出现在字符串中的idx;
for(int i=0;i<128;++i)
{
prePos[i] = -1;
}
// 遍历字符串;
for(int j=0;j<s.length();++j)
{
int preIdx = prePos[s[j]-' ']; // 该字符上次出现的位置;
if(preIdx<0 || j-preIdx>curLength){
++curLength; // 没有出现在当前最长的字符串f(i-1)中
}else{
maxLength = curLength>maxLength?curLength:maxLength;
curLength = j - preIdx;
}
prePos[s[j]-' '] = j;
}
maxLength = curLength>maxLength?curLength:maxLength;
delete[] prePos;
return maxLength;
}