题目
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
思路
由于ASCII字符最多只有128个,按题目的描述应该不会出现中文等其他字符,所以我们可以考虑申请一个长度为128的数组(名为letter),这个数组我们以字符的ASCII码为索引,我们先给数组中的所有值赋值0。然后开始扫描字符串,我们这里以示例一
为例,首先扫描到a,取得a的ASCII码,然后letter[a.charCodeAt()] = 0 + 1
,这里0是a在字符串里的位置,然后扫描第二个字符b,同样的letter[a.charCodeAt()] = 0 + 1
,接下来c,然后当我们遇到再下一个a的时候letter[a.charCodeAt()]
的值不为0,说明我们之前已经遇到过这个字符了,那么我们就可以截取(0, 2)位置的字符串存入maxArr中,然后再把当前新的a的位置存入,也就是 3 + 1,此时我们所认为的最长的数组就是 bca,这是正在扩展中的字符串,它还有无限的可能~~然后已经存入最大数组中的是abc,之后再接着扫描。。。
这个算法的思想就是动态的维护一个最长字符串,只要遇到和当前字符串中有相同字符的就截断当前字符串,然后从相同的字符的下一个开始继续维护
代码
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
const letter = new Array(128); // 记录最长子串的位
let max = 0;
const maxArr = [];
let begin = 0;
for(let i = 0; i < 128; i += 1) {
letter[i] = 0;
}
for (let i = 0; i < s.length ; i += 1) {
const pos = s[i].charCodeAt();
if (letter[pos] !== 0 && letter[pos] > begin) {
maxArr.push(max);
max = i + 1 - letter[pos];
begin = letter[pos];
letter[pos] = i + 1;
} else {
letter[pos] = i + 1;
max += 1;
}
}
maxArr.push(max);
for (let i = 0; i < maxArr.length; i += 1) {
if (max < maxArr[i]) {
max = maxArr[i];
}
}
return max;
};