题目描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。注意 "bca" 和 "cab" 也是正确答案。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke"是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104s由英文字母、数字、符号和空格组成
解决方案:
-
用
map数组(类似哈希表)记录当前窗口中每个字符出现的次数,map[字符]的值表示这个字符在窗口中出现的次数 -
用
left和i分别表示窗口的左右边界(i是当前右边界) -
遍历字符串,每次将新字符加入窗口
-
如果新字符导致窗口中这个字符出现次数 >1(说明有重复),就不断从窗口左边移除字符,直到新字符不重复为止
-
每次窗口合法时,更新最长子串长度
关键点:
-
vector<int> map(128, 0)是因为 ASCII 字符共有 128 个 -
当
map[s[i]] > 1时,说明新加入的字符在窗口中已存在,需要收缩左边界 -
每次循环结束时,窗口
[left, i]内的所有字符都是不重复的 -
时间复杂度 O(n):每个字符最多被加入和移出窗口各一次
函数源码:
cppclass Solution { public: int lengthOfLongestSubstring(string s) { int len=s.length(); int ans=0; int left=0; vector<int>map(128,0); for(int i=0;i<len;i++){ map[s[i]]+=1; while(map[s[i]]>1){ map[s[left]]-=1; left+=1; } ans=max(ans,i-left+1); } return ans; } };