题目描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 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" 是一个子序列,不是子串。
|
- 方法一(自己写的)
- 对每个ASCⅡ字符设置两个标记,一个记录该字符有无出现过,一个记录上次出现的位置
- 步骤如下:
- 设置一个变量,记录以当前位置为尾的最长无重复字符子串的长度
- 从字符串第一个位置开始遍历,如果该字符没有出现过,当前最大长度+1,并记录该位置为当前字符上次出现的位置
- 如果该字符出现过,根据当前最大长度大小更新全局最大长度,将子串长度截取到该字符上一次出现位置的后一位,必须擦除该字符上次出现位置之前出现过的字符,将它们标记为未出现过,因为当前子串起始位置已更改,更新当前最大长度,该字符上次出现位置改为当前位置
- 遍历完该字符串,返回全局最大长度与当前最大长度的最大值,因为该算法只在出现重复字符才更新全局最大长度,所以遍历到最后一个字符可能没有重复,这样的话最后一段子串的长度就不会更新
- 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public: int lengthOfLongestSubstring(string s) { int flag[256],pos[256]; memset(flag,0,sizeof(flag)); int maxlen=0,nowlen=0; for(int i=0;i<s.length();i++){ if(flag[s[i]]){ if(nowlen>maxlen){ maxlen=nowlen; } for(int j=i-nowlen;j<pos[s[i]];j++){ flag[s[j]]=0; } nowlen=i-pos[s[i]]; pos[s[i]]=i; } else{ nowlen++; flag[s[i]]=1; pos[s[i]]=i; } } return maxlen>nowlen?maxlen:nowlen; } };
|
- 方法二(看题解的,但是思想跟我自己想的差不多,只不过这个写起来比较简单)
- 滑动窗口
- 对每个ASCⅡ字符一个标记,记录该字符有无出现过
- 步骤如下:
- 定义一个队列,从头遍历字符串
- 如果当前字符没有出现过,则入队,此时当前最大长度即为队列中的元素个数
- 如果出现过,更新全局最大长度,再逐个出队,知道弹出与当前字符重复的字符为止
- 返回全局最大长度与队列大小的最大值,理由同上
- 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Solution { public: int lengthOfLongestSubstring(string s) { int maxlen=0,flag[256]; queue<char> q; char tmp; memset(flag,0,sizeof(flag)); for(int i=0;i<s.length();i++){ if(flag[s[i]]&&q.size()>maxlen){ maxlen=q.size(); } while(flag[s[i]]){ tmp=q.front(); flag[tmp]=0; q.pop(); } q.push(s[i]); flag[s[i]]=1; } return maxlen>q.size()?maxlen:q.size(); } };
|
return 0;
本文链接:
https://luojinrong.github.io/2019/05/22/leetcode-3/