解题思路:
使用双指针法和哈希表。在循环中,维护一个窗口,使得窗口内的字符串没有重复的字符。具体流程如下:
- 定义一个 map,用于记录字符上一次出现的位置和窗口内出现过的字符。
- 初始化右指针 right 为-1,表示当前窗口内没有字符。
- 循环遍历字符串 s 中的每个字符,同时更新窗口的左右指针。在每次移动左指针的时候,将左指针对应的字符位置在 map 中删除。
- 在更新完左指针之后,使用 while 循环向右移动右指针,如果 map 中不含有下一个字符,则将该字符添加到 map 中,同时更新 right 指针。
- 当右指针到达字符串 s 的末尾或者遇到重复的字符时,结束 while 循环。
- 每次循环更新最长不重复子串的长度 ans,它的值为当前窗口的长度(right - i + 1)和之前的 ans 的较大值。
- 循环结束后,返回最长不重复子串的长度 ans。
时间复杂度:O(n)
空间复杂度:O(1)
// 函数名:lengthOfLongestSubstring
// 函数参数:一个字符串 s
// 函数返回值:一个整数,表示字符串 s 中最长不重复子串的长度
func lengthOfLongestSubstring(s string) int {
// 定义一个 map,用于记录字符上一次出现的位置和窗口内出现过的字符,map 中的 key 为字符,value 为该字符上一次出现的位置。
m := map[byte]int{}
right, ans := -1, 0
// 循环遍历字符串 s 中的每个字符
for i := 0; i < len(s); i++ {
// 如果不是第一个字符,则将左指针对应的字符位置在 map 中删除
if i != 0 {
delete(m, s[i-1])
}
// 右指针向右移动,直到遇到重复的字符或者到达字符串 s 的末尾
for right+1 < len(s) && m[s[right+1]] == 0 {
m[s[right+1]]++ // 将右指针对应的字符添加到 map 中
right++ // 右指针向右移动
}
// 更新最大子串长度 ans
ans = max(ans, right-i+1)
}
return ans // 返回最长不重复子串的长度
}
// 辅助函数,用于计算两个数的最大值
func max(a, b int) int {
if a > b {
return a
}
return b
}