Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
今天我们来看看第三题:无重复字符的最长子串
无重复字符的最长子串
题目描述:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
解题思路
对于此类字符串操作,通常使用滑动窗口来解题。
滑动窗口的思想其实就是动态的移动窗口,而控制这个窗口的关键所在是left、right两个位置,满足条件更新right,不满足条件更新left。
这题中的思路其实就是对字符串进行遍历,通过键值对keyValue来记录字符和字符数量。如果字符数量大于一说明有重复,则操作left,没有则继续操作right。
滑动窗口解法
解法一
class Solution {
func lengthOfLongestSubstring(_ s: String) -> Int {
var res = 0
var window = [Character: Int]()
var left = 0
var right = 0
while right < s.count {
let c = s[s.index(s.startIndex, offsetBy: right)]
right += 1
if window[c] != nil {
window[c]! += 1
} else {
window[c] = 1
}
while let value = window[c], value > 1 {
let d = s[s.index(s.startIndex, offsetBy: left)]
left += 1
if window[d] != nil {
window[d]! -= 1
} else {
window[c] = 1
}
}
res = max(res, right - left)
}
return res
}
}
在以上这个解法中使用的键值对{key: value}key是字符,value是字符出现的数量,所以value没有的到很好的利用,每次左指针右移一位,移除字典中的一个字符,这一步会导致很多无用的循环。while循环发现的重复字符不一定就是字典中最早添加那个,还要好多次循环才能到达,这些都是无效循环,不如直接用map记下每个字符的索引。
在下面的解法中使用keyValue来记录字符和字符的索引index。
解法二
class Solution {
func lengthOfLongestSubstring2(_ s: String) -> Int {
var res = 0
var window = [Character: Int]()
var left = 0
var right = 0
for char in s {
if let value = window[char] {
left = max(value, left)
}
res = max(res, right-left+1)
right += 1
window[char] = right
}
return res
}
}
总结
在解题时,最开始的方法可能不是最优解,但是只要我们的思路是对的就没问题,因为过程中会我们会发现前面的解法存在哪些问题,然后在去优化这些问题,在我看来,只要一直思考就是在进步。