无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
通过次数1,493,543提交次数3,880,908
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这个问题是利用滑动窗口算法来求解字符串最值的一道题。
所谓滑动窗口就是利用双指针模拟一个子区间,通过移动两端的指针来使区间内的内容满足题目的要求,因为我们程序是动态执行的,所以我们怎么移动两端的指针来保持区间内容是符合要求的,就是这个算法的关键
什么时候移动左端指针 —— 缩小窗口
什么时候移动右端指针 —— 扩大窗口
因为程序是顺序执行的,所以在同一时刻,我们只能维护一端的窗口范围。
根据这道题的题目要求,我们需要找出给定字符串的最大不重复子串,因此我们两端指针区间的内容是不应该出现重复字符的。
所以对于两端的移动逻辑应该是这样的。
当指针区间内未出现重复字符时,我们不断移动右端指针,扩大窗口范围
当指针区间出现重复字符时,我们就开始移动左端指针,缩小窗口范围,直至重复的字符消失。
明白了指针的移动之后,我们就需要维护这个过程中的一些关键值,如:如何判断区间内是否存在重复字符,出现后的处理逻辑等,这里不再用文字叙述,详细的看代码。
func lengthOfLongestSubstring(s string) int {
// transfer the string
// 将string 类型转换成 byte 类型,便于使用下表对字符进行访问
str := []byte(s)
strCount, maxCount, counter := len(s), 0, 0
// map 是引用类型的数据,在采用下面方式进行一个map的声明时,这个map是个空值,向其写入内容会引发异常
// var needs map[byte]int
// 因此在你向声明一个未知大小的map时,你应该使用make函数为map数据分配相应的内存空间
needs := make(map[byte]int)
left, right := 0, 0
// decide a time point to shrink the slide window
// which is the appear of the needs array
for right < strCount {
char := str[right]
// 未遇到重复字串时不断扩大右侧窗口边界
needs[char]++
right++
count, _ := needs[ char ]
// 缩小左侧窗口范围
if count > 1{
// 记录本次的最长子串
if counter > maxCount{
maxCount = counter
}
// 重复字符计数
// 直接使用count 好了就不用再使用一个新的变量来进行监控了
for count > 1{
charLeft := str[left]
if needs[charLeft] > 1 {
count--
}
needs[charLeft]--
left++
counter--
}
}
counter++
}
if counter > maxCount {
maxCount = counter
}
return maxCount
}