【LeetCode】【3. Longest Substring Without Repeating Characters】(python版)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_20141867/article/details/81912416

Description:
Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: "abcabcbb"
Output: 3 
Explanation: The answer is "abc", which the length is 3.

Example 2:

Input: "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.

Example 3:

Input: "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3. 
             Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

思路:
题目要求最长无重复子串。

第一种,暴力求解:遍历字符串,每次寻找从当前字符往后延伸,直到末尾或者出现重复字符。中间需要用辅助hash保存已出现过的字符,时间复杂度为 O ( n 2 ) ,空间复杂度为 O ( k ) ,k为字符集大小

第二种:滑动窗口法,用i,j指向窗口的前后下界,如果当前字符未出现在窗口,j后移,如果出现了,i后移。这里窗口用集合实现,判存复杂度为 O ( 1 ) 。总的时间复杂度为 O ( 2 n ) = O ( n ) ,最坏情况为每个字符都被访问两遍(分别作为窗口的头尾),空间复杂度为 O ( k )

算法实现如下:

class Solution(object):
    # 滑动窗口法
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        slen = len(s)
        if slen == 0:
            return 0
        i = j = 0
        charlist = set()
        maxlen = 0
        while i < slen and j < slen:
            # 如果尾字符出未现在集合中,加入集合,指针后移
            if s[j] not in charlist:
                charlist.add(s[j])
                maxlen = max(maxlen, j - i + 1)
                j += 1
            else:
                # 如果尾字符出现在集合当前,由于不知道出现在前面哪个位置,所以从前面依次移除字符。
                charlist.remove(s[i])
                i += 1
        return maxlen

第三种,动态规划:利用已寻找的信息,用字典保存当前字符上一次出现的位置,
dp[j] = i 表示子串s[i…j]是以s[j]字符为结尾的最长无重复子串,那么有:
d p [ 0 ] = 0
当s[j+1]不在s[i…j]中: d p [ j + 1 ] = d p [ j ]
当s[j+1]在s[i…j]中: d p [ j + 1 ] = s [ j + 1 ]
而判断s[j+1]是否在s[i…j]中,只需要比较上一个s[j+1]的位置是否大于i即可。

只需遍历一次字符串,因此时间复杂度为 O ( n ) ,空间复杂度为 O ( k )

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        slen = len(s)
        if slen == 0:
            return 0
        chardict = dict()
        maxlen = 0
        last_start = -1
        for i in range(slen):
            # last_start表示即为dp[i-1]
            last_start = max(last_start, chardict.get(s[i], -1))
            maxlen = max(maxlen, i - last_start)
            chardict[s[i]] = i
        return maxlen

猜你喜欢

转载自blog.csdn.net/qq_20141867/article/details/81912416