给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。
示例 1:
输入:s = "abcabcbb"
输出:3
解释:因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入:s = "bbbbb"
输出:1
解释:因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入:s = "pwwkew"
输出:3
解释:因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
答案
func lengthOfLongestSubstring(_ s: String) -> Int {
var charDict = [Character: Int]()
var maxLength = 0
var left = 0
for (index, char) in s.enumerated() {
if let lastIndex = charDict[char] {
left = max(left, lastIndex + 1)
}
charDict[char] = index
maxLength = max(maxLength, index - left + 1)
}
return maxLength
}
print(lengthOfLongestSubstring("abcabcbb"))
print(lengthOfLongestSubstring("bbbbb"))
print(lengthOfLongestSubstring("pwwkew"))
//3
//1
//3
知识点详解:
子串和子序列的区别是:
子串:字符串中连续的字符组成的序列,比如“pwwkew”中的“wke”就是它的一个子串。
子序列:字符串中一些不一定连续的字符组成的序列,比如“pwwkew”中的“pwke”就是它的一个子序列。
子串一定是子序列,因为子串中的字符绝对是连续的。但是子序列不一定是子串,因为子序列中的字符可以不连续。
滑动窗口定义左右指针表示当前窗口范围,右指针不断向右滑动,根据条件收缩左指针范围,求解最大窗口。
算法思路
- 使用字典来记录每个字符最后一次出现的索引位置
- 每次尝试扩大右边界,检查当前字符是否重复
- 如果重复,移动左指针到重复字符上一次索引 + 1 的位置
- 如果不重复,扩大窗口右边界
- 不断更新最大不重复子串长度
双指针形成滑动窗口是解决子串问题的常用手法之一。
算法执行过程
0.s="abcabcbb",初始化charDict = [:]
1.index = 0, s[0] = 'a', 没重复, left = 0, charDict = ["a": 0], maxLength = 1
2.index = 1, s[1] = 'b', 没重复, left = 0, charDict = ["b": 1, "a": 0], maxLength = 2
3.index = 2, s[2] = 'c', 没重复, left = 0, charDict = ["b": 1, "c": 2, "a": 0], maxLength = 3
4.index = 3, s[3] = 'a', 重复, left = 1, charDict = ["b": 1, "c": 2, "a": 3], maxLength = 3
5.index = 4, s[4] = 'b', 重复, left = 2, charDict = ["b": 4, "c": 2, "a": 3], maxLength = 3
5.index = 5, s[5] = 'c', 重复, left = 3, charDict = ["b": 4, "c": 5, "a": 3], maxLength = 3
6.index = 6, s[6] = 'b', 重复, left = 5, charDict = ["b": 6, "c": 5, "a": 3], maxLength = 3
6.index = 7, s[7] = 'b', 重复, left = 7, charDict = ["b": 7, "c": 5, "a": 3], maxLength = 3
0.s="pwwkew",初始化charDict = [:]
1.index = 0, s[0] = 'p', 没重复, left = 0, charDict = ["p": 0], maxLength = 1
2.index = 1, s[1] = 'w', 没重复, left = 0, charDict = ["p": 0, "w": 1], maxLength = 2
3.index = 2, s[2] = 'w', 重复, left = 2, charDict = ["p": 0, "w": 2], maxLength = 2
4.index = 3, s[3] = 'k', 没重复, left = 2, charDict = ["p": 0, "w": 2, "k": 3], maxLength = 2
5.index = 4, s[4] = 'e', 没重复, left = 2, charDict = ["w": 2, "k": 3, "e": 4, "p": 0], maxLength = 3
5.index = 5, s[5] = 'w', 重复, left = 3, charDict = ["w": 5, "k": 3, "e": 4, "p": 0], maxLength = 3
复杂度
时间复杂度O(n),空间复杂度O(min(m, n)),其中n是字符串长度,m是字符集大小。
BTW
感谢各位简友的宝贵时间与意见!文章难免有疏漏或错误,如有涉及不当之处,还望能够提出宝贵意见。感激不尽!