Skip to content

Latest commit

 

History

History
64 lines (53 loc) · 2.33 KB

3-LongestSubstringWithoutRepeatingCharacters.md

File metadata and controls

64 lines (53 loc) · 2.33 KB

无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

思路: 要返回非重复最长子串的长度,所以子串必须是连续的,我的想法是有一个移动的窗口,从左往右,设一个 left 指针,当成非重复子串的第一个值,如果往右走的过程中,值都不重复,left 不变,记录当前的非重复子串的长度,当第一个重复的值出现时,就把 left 放到第一个出现值的后一位,对比长度,并继续往右走,直到走完数组,得到的结果就是最长非重复子串

  1. 如果字符串的长度为 0,返回 0;
  2. 设一个 left 指针和一个记录长度的 res;
  3. 遍历数组,从左往右,获取这个当前值第一次出现的位置;
  4. 如果这个位置存在,且不小于当前的下标,则计算非重复子串长度
  5. 如果当前值的位置小于其下标,那就将 left 移至位置下一位。
  6. 计算长度
/**
 * @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;
};