给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
思路: 要返回非重复最长子串的长度,所以子串必须是连续的,我的想法是有一个移动的窗口,从左往右,设一个 left 指针,当成非重复子串的第一个值,如果往右走的过程中,值都不重复,left 不变,记录当前的非重复子串的长度,当第一个重复的值出现时,就把 left 放到第一个出现值的后一位,对比长度,并继续往右走,直到走完数组,得到的结果就是最长非重复子串
- 如果字符串的长度为 0,返回 0;
- 设一个 left 指针和一个记录长度的 res;
- 遍历数组,从左往右,获取这个当前值第一次出现的位置;
- 如果这个位置存在,且不小于当前的下标,则计算非重复子串长度
- 如果当前值的位置小于其下标,那就将 left 移至位置下一位。
- 计算长度
/**
* @param {string} s
* @return {number}
*/
const lengthOfLongestSubstring = (s) => {
if (!s.length) return 0;
// res 存储最长无重复子串的长度,初始值为1
let res = 1,
// 来标记滑动窗口的起始位置,初始值为0。
left = 0;
// 遍历字符串 s 对于每一个字符 s[i],查找它在 left 到 i-1 这个区间内是否出现过
for (let i = 0; i < s.length; i++) {
let index = s.indexOf(s[i], left);
// 如果在这个区间内找到了相同的字符,
// 那么更新 left 为该字符的下一个位置。
// 这样就保证了从 left 到 i 这个区间内没有重复的字符。
if (index !== -1 && index < i) left = index + 1;
// 更新 res 的值为当前无重复子串的长度和 res 中存储的最大长度之间的较大值。
res = Math.max(res, i - left + 1);
}
return res;
};