算法1
(双指针) $O(n)$
- i、j 维护相关不重复的子串
- 比如字符串“abcaaabc”
C++ 代码
class Solution {
public:
int longestSubstringWithoutDuplication(string s) {
int i = 0, j = 0;
int res = 0;
unordered_map<char, int>map;
while (j < s.size()){
if (++map[s[j]] > 1 )
{
while(map[s[i]] == 1) map[s[i++]]--;//解决连续两个黏在一起,则需要重新开始
map[s[i++]]--;
}
res = max(res,j - i + 1);
j++;
}
return res;
}
};
算法2
(动态规划)
动态规划,用f(i)表示以i个字符结尾不包含重复子字符串的最长长度,从左向右扫描
1、若第i个字符在之前没出现过,则 f(i) = f(i-1) + 1;
2、若第i个字符在之前出现过,
计算第i个字符距离上次出现之间的距离为d
(a)若d <= f(i-1),则说明第i个字符上次出现在f(i-1)对应的不重复字符串之内,那么这时候更新 f(i) = d
(b)若d > f(i-1),则无影响,f(i) = f(i-1) + 1
C++ 代码
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.length() == 0)
return 0;
int curLen = 0, maxLen = 0;
int* position = new int[26];
for (int i = 0; i < 26; i++)
position[i] = -1;
for (int i = 0; i < s.length(); i++){
int preIndex = position[s[i] - 'a'];
if (preIndex < 0 || i - preIndex > curLen) // 没出现过,或者d>f(i-1)
curLen++;
else{ // 出现过了
if (curLen > maxLen)
maxLen = curLen;
curLen = i - preIndex // f(i) = d
}
position[s[i] - 'a'] = i;
}
if (curLen > maxLen)
maxLen = curLen;
delete[] position;
return maxLen;
};