题目
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
解题思路
方法一 滑动窗口
我们可以使用一个数组arr
来维护滑动窗口。因为寻找的是最长的无重复字串,子串必然是连续的,我们可以在遍历过程中,使用arr
记录字符串中的字符。
- 如果字符不在
arr
中,我们就将该字符push
进数组中。 - 如果字符在
arr
中,我们就将上一次出现的该字符以及之前的数组元素删除。 - 记录每次遍历过后的数组长度,维护一个最大值。
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
var arr = [], max = 0;
for(var i = 0;i<s.length;i++){
var tag = arr.indexOf(s[i]);
if(tag !== -1){
arr.splice(0, tag + 1);
}
arr.push(s[i])
max = Math.max(max , arr.length)
}
return max
};
方法二
我们不仅可以使用数组维护一个滑动窗口,还可以使用下标来维护这个滑动窗口。
- 维护初始窗口
i = 0;j = 0;
- 遍历字符串,让
j
向右滑动,每次滑动之后,查看当前j
位置上的字符是否出现在i~j
这个窗口内- 如果
s[j]
未出现,窗口左侧边界不变,右侧边界继续移动 - 如果
s[j]
已出现,窗口左侧边界右移到上一次s[j]
出现的位置之后,右侧边界继续移动。
- 如果
- 维护一个计数器,记录每次移动后
i~j
的长度,维护一个最大长度。
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
var max = 0;
for(var i = 0,j=0;j<s.length;j++){
var tag = s.substring(i,j).indexOf(s[j]);
if(tag !== -1){
i = i + tag + 1;
}
max = Math.max(max , j - i + 1)
}
return max
};