本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
题目描述:
给定一个字符串,找出其中不含有重复字符的最长子串的长度。
思路分析
首先说一下什么是子串和子序列。
子序列指字符串中不连续的子字符串。
子串指字符串中连续的子字符串。
例如:字符串:123456789; 子序列:13579(非连续),子串:12345(连续)。
回到题目,找出不含有重复字符的最长子串的长度。
例如:字符串"abcabcbb",无重复字符的最长子串是 "abc",所以其长度为 3。
字符串"pwwkew",无重复字符的最长子串是 "wke"或"kew",所以其长度为 3。如果带上p,"pwke"这就是子序列。
实现方法上,可以去遍历字符串,charAt方法拿到每一个字符,用一个变量去存储不重复的子串,同时通过indexOf去判断是否存储过遍历的字符。
代码 Talk is cheap,show you the code
遍历字符串,s.charAt(i)取出每一个字符,str.indexOf(char) 判断当前字符是否已经存在,如果不存在,添加该字符,如果存在,str.substr(index + 1) + char 截取该字符之后的字符串,再加上新的字符,拼凑成新的子串。
const lengthOfLongestSubstring = function (s) {
let result = 0; // 最长子串的长度
let str = ""; // 存放无重复子串
for (let i = 0; i < s.length; i++) {
let char = s.charAt(i);
//判断当前字符是否已经存在
let index = str.indexOf(char);
if (index === -1) {
//字符不存在,添加该字符
str += char;
result = result < str.length ? str.length : result;
} else {
//字符已存在,截取存在字符之后的字符串,再加上新的字符,组成新的子串
str = str.substr(index + 1) + char;
}
}
return result;
};
举个例子 s="pwwkew"
i=0,str="p",result=1
i=1,str="pw",result=2
i=2,此时char="w",str="pw"里包含w字符,位于index=1的位置,str截取,重新赋值后为w,str="w",result=2大于当前str长度,仍为2
i=3,str="wk",result=2
i=4,str="wke" ,result=3
i=5,此时char="w",str="wke"里包含w字符,位于index=0的位置,str截取,重新赋值后为str="kew",result=3
返回值result就是字符的长度。
除了上面的方法,还可以通过滑动窗口的方式来实现,使用两个指针表示字符串中某个子串的左右边界,在每一步的操作中,将左指针向右移动一格,右指针不断地向右移动,保证这两个指针对应的子串中没有重复的字符,枚举结束后,找到最长的子串, 更多详细内容可以参考Leetcode官方的讲解
var lengthOfLongestSubstring = function(s) {
// 哈希集合,记录每个字符是否出现过
const occ = new Set();
const n = s.length;
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
let rk = -1, ans = 0;
for (let i = 0; i < n; ++i) {
if (i != 0) {
// 左指针向右移动一格,移除一个字符
occ.delete(s.charAt(i - 1));
}
while (rk + 1 < n && !occ.has(s.charAt(rk + 1))) {
// 不断地移动右指针
occ.add(s.charAt(rk + 1));
++rk;
}
// 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = Math.max(ans, rk - i + 1);
}
return ans;
};
总结
一开始写无从下手,后面慢慢分析,一行行写,加打印,逐渐排查得出方法。