3.无重复字符的最长子串

难度:中

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

  • 输入: “abcabcbb”
  • 输出: 3
  • 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

  • 输入: “bbbbb”
  • 输出: 1
  • 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

  • 输入: “pwwkew”
  • 输出: 3
  • 解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
  • 注意,你的答案必须是 子串 的长度,”pwke” 是一个子序列,不是子串。

方法1 - 暴力法:

class Solution1(object):
    """暴力法
        遍历检查所有的子字符串,找出无重复的子字符串的最大长度。
        复杂度分析:
            时间复杂度:O(n³)
            空间复杂度:O(min(n, m)),我们需要 O(k) 的空间来检查子字符串中是否有重复字符,
                其中 k 表示 Set 的大小。而 Set 的大小取决于字符串 n 的大小以及字符集/字母 m 的大小。
    """
    def length_of_longest_substr(self, s):
        """计算无重复字符的最长子串的长度
        """
        assert(isinstance(s, str))
        n, ret = len(s), 0
        for i in range(n):
            for j in range(i + 1, n + 1):
                if self._all_unique(s[i:j]):
                    ret = max(ret, j - i)
        return ret
    
    def _all_unique(self, s):
        """给定字符串是否存在重复的字符
        """
        assert(isinstance(s, str))
        d = {}  # using like a set
        for ch in s:
            if ch in d:
                return False
            d[ch] = 0
        return True


l = ['abcabcbb', 'bbbbb', 'pwwkew']
obj = Solution1()
for s in l:
    # ret = %time obj.length_of_longest_substr(s)
    ret = obj.length_of_longest_substr(s)
    print('\"{}\", it\'s length of longest substr: {}'.format(s, ret))

# Output:
# "abcabcbb", it's length of longest substr: 3
# "bbbbb", it's length of longest substr: 1
# "pwwkew", it's length of longest substr: 3

方法2 - 滑动窗口:

class Solution2(object):
    """滑动窗口
        复杂度分析:
            时间复杂度:O(2n) = O(n),最糟糕情况下,每个字符将被 i 和 j 访问两次。
            空间复杂度:O(min(n, m)),与之前的方法相同。
    """
    def length_of_longest_substr(self, s):
        assert(isinstance(s, str))
        d, n, i, j, ret = {}, len(s), 0, 0, 0
        while i < n and j < n:
            if s[j] not in d:
                d[s[j]] = 0
                j += 1
                ret = max(ret, j - i)
            else:
                del d[s[i]]
                i += 1
        return ret


l = ['abcabcbb', 'bbbbb', 'pwwkew']
obj = Solution2()
for s in l:
    # ret = %time obj.length_of_longest_substr(s)
    ret = obj.length_of_longest_substr(s)
    print('\"{}\", it\'s length of longest substr: {}'.format(s, ret))

# Output:
# "abcabcbb", it's length of longest substr: 3
# "bbbbb", it's length of longest substr: 1
# "pwwkew", it's length of longest substr: 3

方法3 - 优化的滑动窗口1:

class Solution3(object):
    """优化的滑动窗口1
        复杂度分析:
            时间复杂度:O(n),索引j会迭代n次
            空间复杂度:O(min(n, m)),与之前的方法相同。
    """
    def length_of_longest_substr(self, s):
        assert(isinstance(s, str))
        d, n, i, ret = {}, len(s), 0, 0
        for j in range(n):
            # v = d.get(s[j])
            # if v is not None:
                # i = max(v, i)
            if s[j] in d:
                i = max(d[s[j]], i)
            ret = max(ret, j - i + 1)
            d[s[j]] = j + 1
        return ret


l = ['abcabcbb', 'bbbbb', 'pwwkew']
obj = Solution3()
for s in l:
    # ret = %time obj.length_of_longest_substr(s)
    ret = obj.length_of_longest_substr(s)
    print('\"{}\", it\'s length of longest substr: {}'.format(s, ret))

# Output:
# "abcabcbb", it's length of longest substr: 3
# "bbbbb", it's length of longest substr: 1
# "pwwkew", it's length of longest substr: 3

方法4 - 优化的滑动窗口2:

class Solution4(object):
    """优化的滑动窗口2
        复杂度分析:
            时间复杂度:O(n),索引j会迭代n次
            空间复杂度:O(m),m是字符集的大小
    """
    def length_of_longest_substr(self, s):
        assert(isinstance(s, str))
        array = [0 for _ in range(128)]
        n, i, ret = len(s), 0, 0
        for j in range(n):
            i = max(array[ord(s[j])], i)
            ret = max(ret, j - i + 1)
            array[ord(s[j])] = j + 1
        return ret


l = ['abcabcbb', 'bbbbb', 'pwwkew']
obj = Solution4()
for s in l:
    # ret = %time obj.length_of_longest_substr(s)
    ret = obj.length_of_longest_substr(s)
    print('\"{}\", it\'s length of longest substr: {}'.format(s, ret))

# Output:
# "abcabcbb", it's length of longest substr: 3
# "bbbbb", it's length of longest substr: 1
# "pwwkew", it's length of longest substr: 3