请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是
"abc",所以其
长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是
"b"
,所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是
"wke"
,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,
"pwke"
是一个子序列,不是子串。
提示:
s.length <= 40000
注意:本题与主站 3 题相同:力扣
思路:参考题解 力扣 及 注释,利用滑动窗口(start、end可随时调整)
时间复杂度:优化前 O(N^2) → 优化后 O(N),空间换时间
空间复杂度:优化前 O(1) → 优化后 O(N),空间换时间
// 方法1-滑动窗口 利用map优化前:funclengthOfLongestSubstring(sstring) int { // start:不含重复子串的起点;end:不含重复子串的终点;length:当前已匹配不重复子串长度;maxLength:目前已匹配最长子串长度start, end, length, maxLength, sLength :=0, 0, 0, 0, len(s) forend<sLength { cmpChar :=s[end] // 过滤重复字符:将cmpChar与s[start:end]的字符逐个比较。比如abbbc,最终会跳过中间的bbbfori :=start; i<end; i++ { ifs[i] ==cmpChar { start=i+1// 若出现重复字符,start跳过重复字符,指向重复字符的下一位置length=end-start// 计算length时外循环中会对length++,所以这里暂时无需+1操作break// s[start:end]中已经存在相同字符,break退出进行下一轮外循环 } } length++end++// 扩展右边界maxLength=max(maxLength, length) } returnmaxLength} // 方法2-滑动窗口 利用map优化后:funclengthOfLongestSubstring(sstring) int { // start:不含重复子串的起点;end:不含重复子串的终点;length:当前已匹配不重复子串长度;maxLength:目前已匹配最长子串长度start, end, length, maxLength, sLength :=0, 0, 0, 0, len(s) lastIndexMap :=make(map[byte]int) // 存储已遍历过的字符最后出现的下标位置forend<sLength { cmpChar :=s[end] // 仅当当前要遍历的 s[start,end) 中已存在 cmpChar = s[end] 时更新startiflastIndex, ok :=lastIndexMap[cmpChar]; ok&&lastIndex>=start { start=lastIndex+1length=end-start } lastIndexMap[cmpChar] =endlength++end++// 扩展右边界maxLength=max(maxLength, length) } returnmaxLength} funcmax(a, bint) int { ifa>b { returna } returnb}