LeetCode-Python-159. 至多包含两个不同字符的最长子串

给定一个字符串 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 

 

你可能感兴趣的:(Leetcode,Python)