159. Longest Substring with At Most Two Distinct Characters.
1 暴力法
Time Limit Exceeded ``` class Solution(object): def lengthOfLongestSubstringTwoDistinct(self, s): """ :type s: str :rtype: int """ res = 0 n = len(s) if n < 3: return n
for i in range(n - 1):
dic = {}
dic[s[i]] = 1
for j in range(i + 1, n):
if s[j] not in dic:
dic[s[j]] = 1
if len(dic) > 2:
break
res = max(res, j - i + 1)
return res
## 分析
我们每次遇到第三个字符的时候,都回到 i 并移一位,这种做法是不是可以优化呢?
我们来看个例子:1 1 1 2 1 1 1 1 2 1 1 2 3
我们访问过第一个 1 之后,从第二个 1 开始,不可能比从第一个 1 开始搜索得到的长度更长。
那从第一个 2 开始呢?
也是不可能的,因为它之后还有 1 ,到 3 的时候,还是要比第一个 1 得到的长度短。
那么下一个下标从哪里开始呢?
答案是,从第三个字符往前看,找到前一个字符,如果前面是一组连续的相同的字符(连续的 1 或者连续的 2 都可以)的开始的位置。
当然,在实现的时候,我们会记录下来这个位置的前一位。下面看代码实现:
## Python
class Solution(object): def lengthOfLongestSubstringTwoDistinct(self, s): """ :type s: str :rtype: int """ res = 0 n = len(s) if n < 3: return n
i = 1
fc = 0 # begin of first char
efc = 0 # end of first char
sc = None
while i < n:
if s[fc] == s[i]: # if is the first character, continue
efc = i
i += 1
continue
if sc is None: # if is not the first character, and not found seconde character yet.
sc = i
i += 1
continue
if s[sc] == s[i]: # if is the second character
sc = i
i += 1
continue
res = max(res, i - fc) # a third character occurs, update the result.
next_fc = min(efc, sc) + 1 # find the next first char.
fc, efc, i = next_fc, next_fc, next_fc + 1 # update parameters.
sc = None
return max(res, i - fc) # in case, the longest substring in the end.
## C
int lengthOfLongestSubstringTwoDistinct(char* s) { if (strcmp(s, "") == 0) return 0; int fc = 0; int efc = 0; int i = 1; int sc = -1; int res = 0;
while (*(s + i) != '\0') {
if (*(s + i) == *(s + fc)) {
efc = i;
i += 1;
continue;
}
if ((sc == -1) | *(s + sc) == *(s + i)) {
sc = i;
i += 1;
continue;
}
res = i - fc > res ? i - fc : res;
int next_fc = 1 + (sc > efc ? efc : sc);
fc = next_fc;
efc = next_fc;
sc = -1;
i = next_fc + 1;
}
return i - fc > res ? i - fc : res;
} ```