leetcode3. 无重复字符的最长子串

87 阅读1分钟

image.png

解题思路

以字符串的每个字符为起始,找出不包含重复字符的最长子串 以字符串pwwkew为例,有如下情况:

  1. (pw)wkew
  2. pw(wke)w

可以看出规律:

  1. 依次递增地枚举子串的起始位置,那么子串的结束位置也是递增的
  2. 假设选择字符串中的第left个字符作为起始位置,并且得到了不包含重复字符的最长子串的结束位置为right。那么,选择第left+1个字符作为起始位置时,首先从left+1 到right的字符同样不重复。

代码实现

var lengthOfLongestSubstring = function (s) {
  if (s.length <= 1) {
    return s.length;
  }
  let m = {};
  let left = (right = maxLength = 0);
  while (right < s.length) {
    let c = s[right]; // current char
    if (!(m[c] === undefined || m[c] < left)) {
      left = m[c] + 1;
    }
    m[c] = right;
    maxLength = Math.max(maxLength, right - left + 1);
    right++;
  }
  return maxLength;
};

使用了类似滑动窗口的思想,用一个哈希表来记录每个字符最后一次出现的位置,然后使用左右指针来维护一个滑动窗口,保证窗口内的字符都是不重复的。当遇到重复字符时,将左指针移动到重复字符的下一个位置,保证窗口内的字符都是不重复的。同时,记录下窗口的最大长度,最后返回即可。

这个算法的时间复杂度是 O(n),其中 n 是字符串的长度。因为只需要遍历一遍字符串,所以时间复杂度是线性的。空间复杂度也是 O(n),因为需要使用一个哈希表来每个字符最后一次出现的位置