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

示例 1: 输入: “abcabcbb” 输出: 3

解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

输入: “bbbbb”

输出: 1

解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

输入: “pwwkew”

输出: 3

解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。

请注意,你的答案必须是 子串 的长度,”pwke” 是一个子序列,不是子串。

方法

从每一个字符开始的,不包含重复字符的最长子串
image.png
如果我们依次递增地枚举子串的起始位置,那么子串的结束位置也是递增的!这里的原因在于,假设我们选择字符串中的第 LeetCode-3.无重复字符的最长子串 - 图2 个字符作为起始位置,并且得到了不包含重复字符的最长子串的结束位置为 LeetCode-3.无重复字符的最长子串 - 图3 。那么当我们选择第 LeetCode-3.无重复字符的最长子串 - 图4 个字符作为起始位置时,首先从 LeetCode-3.无重复字符的最长子串 - 图5LeetCode-3.无重复字符的最长子串 - 图6 的字符显然是不重复的,并且由于少了原本的第 LeetCode-3.无重复字符的最长子串 - 图7 个字符,我们可以尝试继续增大 LeetCode-3.无重复字符的最长子串 - 图8,直到右侧出现了重复为止。

  1. class Solution {
  2. public:
  3. int lengthOfLongestSubstring(string s) {
  4. unordered_set<char> occ;
  5. int n=s.size();
  6. int rk=-1;
  7. int ans=0;
  8. for(int i=0;i<n;i++){
  9. if(i!=0){
  10. occ.erase(s[i-1]);
  11. }
  12. while(rk+1<n&&!occ.count(s[rk+1])){
  13. occ.insert(s[rk+1]);
  14. rk++;
  15. }
  16. ans=max(ans,rk-i+1);
  17. }
  18. return ans;
  19. }
  20. };