剑指 Offer 48. 最长不含重复字符的子字符串

题目描述

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • $s.length <= 40000$

注意:本题与主站 3 题相同:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/


算法

(哈希表,双指针算法) $O(n)$

用哈希表存储每个字符出现的次数,且保证区间 $[i, j]$ 内没有重复元素,每个字符只出现一次;$res$ 记录答案。

双指针扫描字符串

  1. 每次将 $s[i]$ 加入到哈希表中
  2. 如果 $s[i]$ 出现的次数超过 1,说明在 $[j, i - 1]$ 中有重复元素,此时移动 $j$ 指针直到区间 $[j, i]$ 中没有重复元素为止。
  3. 计算区间长度即当前不含重复字符的字符串的长度,更新 res,res = max(res, i - j + 1)

时间复杂度

$i, j$ 最多扫描一遍字符串,所以时间复杂度为 $O(n)$

空间复杂度

$O(n)$

C++ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<int, int> cnt;
int res = 0;
for (int i = 0, j = 0; i < s.size(); i ++ ) {
cnt[s[i]] ++ ;
while (cnt[s[i]] > 1) cnt[s[j ++ ]] -- ;
res = max(res, i - j + 1);
}
return res;
}
};
Author: tonngw
Link: https://tonngw.com/2022/07/09/剑指 Offer/剑指 Offer 48. 最长不含重复字符的子字符串/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.