![35579fa753690bcb417611d94444dd74.png](https://i-blog.csdnimg.cn/blog_migrate/d5da7b50ea1eb51191db22a47bbac88e.jpeg)
题目来源
传送门
题目描述
给定一个字符串,找出不含有重复字符的 最长子串 的长度。
示例
给定 "abcabcbb" ,没有重复字符的最长子串是"abc",那么长度就是3;给定 "bbbbb" ,最长的子串就是 "b",长度是1;给定 "pwwkew",最长子串是"wke",长度是3。请注意答案必须是一个子串,"pwke"是子序列而不是子串
思路分析
以 abcabcbb 为例,要找到子串,首先遍历每个字符;其次要找到最长的那个,肯定是要有参照对象,我需要一个变量 str 去缓存当前最长子串;我们最终要得到的是子串的长度,所以还需要定义变量 maxLen,当发现新元素时更新 str 和 maxLen。
如果字符 s[i],不在 str 中,那么更新 str 和 maxLen;相反,重新截取并生成新的 str,这时的 str 肯定不是最长,str.length 小于或等于 maxLen,因此不用更新 maxLen;
这里有个非常细节的地方:
maxLen = maxLen < str.length ? str.length : maxLen;
maxLen是通过 str.length 来更新的,但是为什么还需要三目运算?
举例来说 nfpdmpi,maxLen 最大为5,遍历结束后 str 为 dmpi,长度为4,所以需要取较大值。
最终代码如下
function lengthOfLongestSubstring(s) {
let maxLen = 0; // 最长无重复子串的长度
let str = ''; // 当前无重复子串,即活动窗口
const l = s.length; // 目标字符串的长度
for (let i = 0; i < l; i++) {
let chart = s[i];
let index = str.indexOf(chart); // 找出chart在窗口中的位置
if (index === -1) {
str += chart; // 如果chart不在窗口中,则扩大窗口
maxLen = maxLen < str.length ? str.length : maxLen; // 更新maxLen;窗口中子串的长度和maxLen之间取最大值
} else {
// 如果chart在窗口中,则表示字符重复,重新给str赋值
// substring表示截取字符串,但不应该包含当前位置,所以要index+1
str = str.substring(index + 1) + chart;
}
}
return maxLen;
}