LeetCode题解 3. 无重复字符的最长子串
Author:baiyucraft
BLog: baiyucraft’s Home
一、题目描述
题目地址:3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的最长子串
的长度。
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
输入: s = “”
输出: 0
二、思路以及代码
此题一般最无脑的做法肯定是暴力解法,即遍历每个字符串,找出以该字符开头,不包含重复字符的最长子串。所以在解题前,我们先用abcabcbb
这个字符串来模拟暴力解法搜索无重复字符的最长子串的过程:
可以发现一点,如果我们依次递增地枚举子串的起始位置,那么子串的结束位置也是递增的,原理其实很简单,当我们枚举第i个字符开头的子串时,长度为k的子串不重复,长度为k+1的子串重复,即s的i
->i+k
子串中无重复元素,那显然 i+1
->i+k
子串中也无重复元素,并且我们可以继续尝试增大该子串,直到子串中出现了重复元素。这样一来就有了滑动窗口这一概念。
1.滑动窗口
思路: 我们使用左右指针left
和right
来确定滑动窗口的边界。在之后的的操作中,左指针向右移动一格,右指针保证左右指针范围内的是无重复字符的最大子串我,并用max_len
记录下这个子串的长度。其中用集合set类型的ooc
来存储判断子串中的字符是否重复。
动画:
代码:
1 |
|
复杂度分析:
时间复杂度:
空间复杂度:,为字符集大小
2.滑动窗口-优化
思路: 在上文中,我们会发现滑动的过程中left
要枚举s
中的每一个数,并且right
也要枚举s
中的每一个数,那么有什么办法能优化窗口呢?
我们想到用右边界right
来枚举字符串中的每一个字符,用名为c_dic
的字典来存储字符的同时,存储该字符离right
最近的下标。
left
左侧边界初值为0,每次枚举right
向右移动一格时:
- 如果该字符在
c_dic
中,说明是个重复字符,这时:- 若
left
小于等于该字符上一次出现的下标,说明该窗口中的子串重复,则将left
替换为该字符上一次出现的下标的后一个位置,并且将该字符下标更新为right
- 若
left
大于该字符上一次出现的下标,则继续以left
为左边界来枚举
- 若
- 如果该字符不在
c_dic
中,则存入并记录该次枚举后right - left + 1
的值并与max_len
比较替换
动画:
代码:
1 |
|
复杂度分析:
时间复杂度:
空间复杂度:,为字符集大小