1. var lengthOfLongestSubstring = function(s) {
  2. let obj = {};
  3. let left = 0, right = 0;
  4. let maxLen = 0, maxStr = '';
  5. while (right < s.length) {
  6. let c = s[right];
  7. right++;
  8. if (obj[c]) obj[c]++;
  9. else obj[c] = 1
  10. while (obj[c] > 1) {
  11. let d = s[left];
  12. left++;
  13. obj[d]--;
  14. }
  15. if (maxLen < right - left) {
  16. maxLen = right - left;
  17. }
  18. }
  19. return maxLen;
  20. };

容易理解版本 (滑动窗口)

  1. var lengthOfLongestSubstring = function(s) {
  2. // 哈希集合,记录每个字符是否出现过
  3. const occ = new Set();
  4. const n = s.length;
  5. // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
  6. let rk = -1, ans = 0;
  7. for (let i = 0; i < n; ++i) {
  8. if (i != 0) {
  9. // 左指针向右移动一格,移除一个字符
  10. occ.delete(s.charAt(i - 1));
  11. }
  12. while (rk + 1 < n && !occ.has(s.charAt(rk + 1))) {
  13. // 不断地移动右指针
  14. occ.add(s.charAt(rk + 1));
  15. ++rk;
  16. }
  17. // 第 i 到 rk 个字符是一个极长的无重复字符子串
  18. ans = Math.max(ans, rk - i + 1);
  19. }
  20. return ans;
  21. };

最优解

  1. function lengthOfLongestSubstring( s) {
  2. let index = new Array(128);
  3. let len = 0;
  4. let length = s.length();
  5. for (int i = 0, j = 0; j < length; j++) {
  6. // 如果存在重复字符,则获取最大的下标
  7. i = Math.max(index[s.charCodeAt(j)], i);
  8. // 每轮都拿之前与【当前字符一样】最大的下标跟当前下标的差做为最大的字串长度
  9. len = Math.max(len, j - i + 1);
  10. index[s.charCodeAt(j)] = j + 1;
  11. }
  12. return len;
  13. }

至少有 K 个重复字符的最长子串

  1. /**
  2. * @param {string} s
  3. * @param {number} k
  4. * @return {number}
  5. */
  6. var longestSubstring = function(s, k) {
  7. let ans = 0
  8. const n = s.length
  9. for(let p = 1; p <= 26; p++){
  10. const count = new Array(26).fill(0)
  11. for(let i = 0, j = 0, tot = 0, sum = 0; i < n; i++){
  12. const u = s[i].charCodeAt() - 97 ;
  13. count[u]++
  14. if(count[u] == 1) tot++
  15. if(count[u] == k) sum++
  16. while(tot > p){
  17. const t = s[j++].charCodeAt() - 97;
  18. count[t]--
  19. if(count[t] == 0) tot--;
  20. if(count[t] == k - 1) sum--;
  21. }
  22. if(tot === sum) ans = Math.max(ans, i - j + 1)
  23. }
  24. }
  25. return ans
  26. };

至多包含 K 个不同字符的最长子串

  1. /**
  2. * @param {string} s
  3. * @param {number} k
  4. * @return {number}
  5. */
  6. var lengthOfLongestSubstringKDistinct = function(s, k) {
  7. let l = 0, ans = 0;
  8. const map = new Map();
  9. const len = s.length;
  10. for(let i = 0; i < len; i++) {
  11. let c = s[i];
  12. if(map.get(c)) {
  13. map.set(c, map.get(c) + 1);
  14. } else {
  15. map.set(c, 1);
  16. }
  17. while (map.size > k) {
  18. let ch = s[l];
  19. map.set(ch, map.get(ch) - 1);
  20. if (map.get(ch) === 0) {
  21. map.delete(ch);
  22. }
  23. l++;
  24. }
  25. ans = Math.max(ans, i - l + 1);
  26. }
  27. return ans;
  28. };