给定一个字符串 s ,找出 至多 包含两个不同字符的最长子串 t 。
示例 1:
输入: "eceba" 输出: 3 解释: t 是 "ece",长度为3。
示例 2:
输入: "ccaabbb" 输出: 5 解释: t 是 "aabbb",长度为5。
思路:
观察一下,发现可以用sliding window来解,
用left和right表示window的左边界和右边界,
用queue记录当前在window里的字符,
用last_pos记录 当前在window里的字符的最后一次出现的下标。
让right逐个向右扫描, 每次遇到一个新元素char = s[right]时,
1. 如果char已经在queue里,说明非常好不需要额外处理,只需要更新last_pos,last_pos[char] = right
2. 如果char不在queue里
a.如果queue的size < 2,说明还有空位可以直接放进去,然后再在last_pos里记录last_pos[char] = right
b.如果queue的size >= 2,说明要踢人了,queue中的两个元素里必须有一个滚蛋,
怎么决定踢哪个呢?
思路有点类似LRU, 如果一个元素上一次出现是在下标为3, 另一个上一次出现是下标为4,当前下标为5,
应该选择踢下标为3的那个,为了保证新的子串更长。
class Solution(object):
def lengthOfLongestSubstringTwoDistinct(self, s):
"""
:type s: str
:rtype: int
"""
left, right = 0, 0
queue = []
last_pos = {}
res = 0
for right in range(len(s)):
if s[right] in queue:
last_pos[s[right]] = right
elif s[right] not in queue:
if len(queue) >= 2:
if last_pos[queue[0]] < last_pos[queue[1]]: #把0号元素踢掉
left = last_pos[queue[0]] + 1
last_pos.pop(queue[0])
queue.pop(0)
else:
left = last_pos[queue[1]] + 1
last_pos.pop(queue[1])
queue.pop(1)
queue.append(s[right])
last_pos[s[right]] = right
# print s[left:right + 1]
res = max(res, right - left + 1)
return res
return res