问题描述
给定一个字符串,找出不含有重复字符的 最长子串 的长度。
示例:
给定"abcabcbb"
,没有重复字符的最长子串是"abc"
,那么长度就是3。
给定"bbbbb"
,最长的子串就是"b"
,长度是1。
给定"pwwkew"
,最长子串是"wke"
,长度是3。请注意答案必须是一个 子串 ,"pwke"
是 子序列 而不是子串。
题解
方法一、暴力法
通过不同寻找字符串的子串来确定是不是最长的子串。
function lengthOfLongestSubstring(s) {
let str = '', len = 0, maxLen = 0
if (s.length === 1) return 1
for(let i = 0, length = s.length; i < length; i++) {
if (maxLen == length - i) { // 当剩余数量与最大长度相同时跳出循环
break
}
str += s.charAt(i)
len ++
for(let j = i + 1; j < length; j++) {
if (str.indexOf(s.charAt(j)) < 0) {
str += s.charAt(j)
len ++
if (j == length - 1) {
len > maxLen && (maxLen = len)
len = 0
str = ''
}
} else {
len > maxLen && (maxLen = len)
len = 0
str = ''
break
}
}
}
return maxLen
}
方法二、滑动窗口
滑动窗口:窗口每次向右移动,每当遇到不重复的字符,将其添加至窗口,遇到重复字符时,将起始位置移动至重复字符的下一个字符。
滑动窗口滑动过程图解:
function lengthOfLongestSubstring2(s) {
let map = new Map();
let res = 0;
for(let i = 0, j = 0, length = s.length; i < length; i++) {
if (map.has(s.charAt(i))) {
j = Math.max(map.get(s.charAt(i)), j); // 避免start前移
}
map.set(s.charAt(i), i + 1);
res = Math.max(res, i + 1 - j)
}
return res;
}