题目描述
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例2
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例3
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示
s.length <= 40000
算法分析
用一个map(哈希实现)记录字符串中出现过的字符(key为该字符,value为该字符上次出现的位置),start记录当前不含重复字符的子字符串起点。对于第i个字符来说,若
- 第i个字符之前未出现过,当前字符串长度加一,在map中将prevIndex替换为i
- 第i个字符之前出现过,在map中查找到第i个字符最近一次出现的位置prevIndex,start = prevIndex + 1;cur等于 i - prevIndex + 1;并且在map中将prevIndex替换为i
复杂度分析
问题规模为字符串长度n
- 时间复杂度:O(n),需要遍历一遍字符串
- 空间复杂度:O(1),map长度小于等于ASCII码范围,可看做常数
Golang代码如下
func lengthOfLongestSubstring(s string) (max int) {
m := make(map[byte]int)
start, cur := 0, 0
for k, v := range s {
if _, ok := m[byte(v)]; !ok {
m[byte(v)] = k
cur++
} else {
if start > m[byte(v)] {
m[byte(v)] = k
cur++
} else {
cur = k - m[byte(v)]
start = m[byte(v)] + 1
m[byte(v)] = k
}
}
if max < cur {
max = cur
}
}
return
}