携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
无重复字符的最长子串
给定一个字符串
s
,请你找出其中不含有重复字符的 最长子串 的长度。
分析
- 找出不含重复字符的最长子串,所以要对字符串进行遍历,最终的最长子串的长度是有条件的,因此,使用滑动窗口来管理遍历到的子串,为了确定子串的长度,有两种方法
双指针+对象
- 使用两个指针,分别指向没有重复字符的子串的首尾,左指针和右指针均从0开始,右指针一直在左指针的右边,右指针不断向右移动,直到右指针和左指针指向的字符相同,此时记录子串长度,接着左指针向右移动,右指针继续向右移动,在找到和左指针重复的位置,依次类推,直到遍历结束,因此时间复杂度是O(n),只用了两个指针的空间
代码
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let size = s.length
let vis = {}
let len = 0
for(let left=0,right=0;right < s.length;right++) {
if(!vis[s[right]]) {
vis[s[right]]=1
} else {
vis[s[right]]++
}
while(vis[s[right]] > 1) {
vis[s[left++]]--
}
len = Math.max(len, right - left +1)
}
return len
};
复杂数据结构(Map/Set)
- 遍历过程中,把字符串的字符使用Map/Set维护起来,当碰到重复的字符时,获取当前数据结构中元素的个数即无重复字符的子串的长度,然后把这个数据结构中重复的字符删掉,继续遍历,遍历到的和复杂数据结构中的字符不同的字符时,添加到数据里,遍历结束,即可得到无重复字符子串的最长的长度。时间复杂度也是O(n),但是空间复杂度会比较高
- 因为set数据具有唯一性,以Set作为例子
代码
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let maxLength = 0
let left = 0
let charSet = new Set()
for (let right = 0; right < s.length; right++){
while (charSet.has(s[right])){
charSet.delete(s[left])
left += 1
}
charSet.add(s[right])
maxLength = Math.max(maxLength, right - left + 1)
}
return maxLength
};
总结
- 对字符串子串操作的题目中,指针相对来说比较轻巧灵便,在一些字符串的题目中,双指针算的上是一个推荐的解法
- 今天也是有收获的一天