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

115 阅读1分钟

image.png

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第27天,点击查看活动详情

测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。

怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~

一、题目描述:

  • 题目内容

    image.png

  • 题目示例

    image.png

  • 题目解析

    • 0 <= s.length <= 5 * 104
    • s 由英文字母、数字、符号和空格组成

二、思路分析:

我们拿本题,是一道在测试笔试过程中出现的高频题,小白在去年做过该题,回过头来看面试时候如果这样写,可能大概率被叫回去等通知吧,趁周末重新温故一下,学习一下大佬们解题思路。

我们读取题目,要求在一串字符串中求出最长无重复的子串,题目内容简单直白,但是还是需要注意题目给出的字符串类型:

  • 字符串s是由英文、数字、符号和空格组成
  • 返回的内容是连续的子串,位置不能发生变化

根据题目内容,我们能立即想到使用双指针滑动窗口来遍历字符串s,找出无重复的且长度最长的子串。

  • 方法一:字符串分片法

    • 定义两个指针left,right分别指向字符串s索引0的位置
    • 使用for循环,遍历字符串s的长度
    • 当 s[index] 不在 s[left:right]内时,则right指针向右移动一步+1
    • 当 s[index] 在 s[left:right]内时,则left指针被s[index]在s[left:right]内的索引+1,且right指针向前移动
    • 子串长度取max(maxlLenght,right-left)
    class Solution(object):
        def lengthOfLongestSubstring(self, s):
            """
            :type s: str
            :rtype: int
            """
            left, right = 0, 0
            MaxLenght = 0
            for index in range(len(s)):
                if s[index] not in s[left:right]:
                    right+=1
                else:
                    left+=s[left:right].index(s[index])+1
                    right+=1
                MaxLenght=max(right-left,MaxLenght)
            return MaxLenght
    
  • 方法二:使用集合来排除重复元素

    • 定义一个curset集合来存储,不是重复的元素
    • 同理定义两个指针left,right,分别指向字符串s开始位置
    • 使用while循环遍历字符串,当right指针大于len(s)位置退出
    • 当s[right]不在curset集合时,则curset.add(s[right]), right指针继续向右移动一步
    • 子串的长度更新为max(ans,right-left)
    • 当s[right]存在于curset集合中时,则需要遍历curset并删除其元素s[left]元素,left向右移动+1,直到s[right] 在curset()不存在
    class Solution(object):
        def lengthOfLongestSubstring(self, s):
            """
            :type s: str
            :rtype: int
            """
            ans = 0
            left,right = 0,0
            curset = set()
    
            while right < len(s):
                if s[right] not in curset:
                    curset.add(s[right])
                    right +=1
                    ans = max(ans,right-left)
                else:
                    while s[right] in curset:
                        curset.remove(s[left])
                        left +=1
    
            return ans
    
  • 方法三:哈希表方法

    • 创建一个字典类型的smap,字符串s字符作为key,字符的索引作为value
    • 定义开始位置为lk,并赋值为-1,还没有开始指向字符串s
    • 使用for循环遍历字符串s,当ss不在smap中时,则更新字典smap[ss] = i
    • 子串长度更新为max(ans,i-lk)
    • 当字符ss存在smap中,且smap[ss]的索引是大于lk位置时,则lk位置被更新为smap[ss]
    • 同时smap[ss]位置更新为当前索引值i
    class Solution(object):
        def lengthOfLongestSubstring(self, s):
            """
            :type s: str
            :rtype: int
            """
            smap = {}
            ans = 0
            lk = -1
            for i,ss in enumerate(s):
                if ss in smap and smap[ss] > lk:
                    lk = smap[ss]
                    smap[ss] = i
                else:
                    smap[ss] = i
                    ans = max(ans,i-lk)
            return ans
    

三、总结:

本题考察对字符串进行遍历滑动窗口的应用,难点在于对重复的字符处理,本题可以使用字典来记录之前的索引位置,并更新在开始位置,这样可以快速查找,AC提交记录如下: image.png

  • 时间复杂度:O(n),n 为字符串s的长度
  • 空间复杂度:O(N),N 为字符串s中出现的重复元素

以上是本期内容,欢迎大佬们点赞评论,下期见~~~