持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
题目描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列, 不是子串。
提示:
0 <= s.length <= 5 * 104s由英文字母、数字、符号和空格组成
解题思路
- 最直接的思路是两重for循环枚举所有子串,对每一个子串统计是否有重复的部分。时间复杂度来到了O(n^3)。超过了题目限制,就不再实现了。
- 我们可以注意到子字符串的左边界总是在右边界左边,可以用两个指针去表示。可以左右边界从0开始,右边界一直向右走,统计现在左右边界之间是否有重复,如果有,可以将左指针向右走,直到没有重复的字母。重复刚才过程,并记录最大长度。这也叫滑动窗口,像一个可变长的窗口在滑动。由于左右指针只从左到右一次,时间复杂度为O(n)。
- 这里数组记录对应字母出现的下标+1,如果遍历发现值>0 说明出现过
func lengthOfLongestSubstring(s string) int {
a := [128]int{}
l := 0
maxLength := 0
for r := 0; r < len(s); r++ {
if a[s[r]] > l {
l = a[s[r]]
}
a[s[r]] = r + 1
if r-l+1 > maxLength {
maxLength = r - l + 1
}
}
return maxLength
}
- 如果用map记录字母的次数,时间和数组差不多,但是空间会额外O(n)
func lengthOfLongestSubstring(s string) int {
a := make(map[byte]int)
l := 0
maxLength := 0
for r := 0; r < len(s); r++ {
if idx, ok := a[s[r]]; ok && idx >= l {
l = idx + 1
}
a[s[r]] = r
if r-l+1 > maxLength {
maxLength = r - l + 1
}
}
return maxLength
}