无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
我的思路:
用一个map<char,int>来储存信息,char位置用来存字母,int位置来存储char最后出现的位置,最后用当前位置减去前面重复的字母最后出现的位置即得到当前不重复字符串的长度。我用left代表不重复子串的左边界,我用right代表不重复子串的右边界(这是重点)。一遍for循环搞定。话不多说,我代码注释比较详细。
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
map<char, int> m;//保存字符最后出现位置
int left = 0;//不重复字符串的左边界
int right = 1;//不重复字符串的右边界,也可以说是当前边界,右边界减去左边界即得到最长字符串长度
int max1 = 0;//保存最大的不重复字符串的长度
for (int i = 0; i < s.length(); ++i)
{
if (m.count(s[i]) && m[s[i]] > left)//当前字符存在并且状态(位置)比left(不重复字符串的左边界)新(位置比left靠后)
{
left = m[s[i]];//把left的状态改成当前状态(左边界的位置)
}
m[s[i]] = right;//更新当前字母的最新出现的状态(位置)
max1 = max(max1, right - left);//求出最大值
right++;//下一个字母的位置
}
return max1;
}
};
拓展
在上面那个题的前提下增加一个条件:一个字符串字符串不重复超过k个不算重复(我这里以不重复超过两个为例)
比如说
输入: "pwwkew"
输出: 5
解释: 如果仅仅是无重复字符的话,那么最长子串是 "wke",所以其长度为 3。
但如果加上一个条件,比如单个字母重复不超过两次不算重复,那么,这道题的答案就是5,那么最长子串是 "pwwke"。
我的思路:
其实我就在上一题的答案上加入了一点点的修改,我把记录用的map<char,int>改成了map<char, queue<int>> m,用队列来储存当前字符的每一次状态。这道题LeetCode上没有,我只能自己写字符串验证
代码:
int lengthOfLongestSubstring(string s) {
map<char, queue<int>> m;
int left = 0;
int right = 1;
int max1 = 0;
for (int i = 0; i < s.length(); ++i)
{
if (m.count(s[i]) && m[s[i]].size() == 2)//当记录的状态超过2次的时候,说明要出队了,弹出一个状态,然后下面将会记录新的状态
//上面的2可以改成k,代表不重复k次也算有效
{
int f = m[s[i]].front();
m[s[i]].pop();
if (f > left)//如果当前状态值比left新,即更新left,如果比left旧,直接抛弃
{
left = f;
}
}
m[s[i]].push(right);//把最新状态入队
max1 = max(max1, right - left);
right++;
}
return max1;
}
后记:笔者面试字节跳动的时候,这个拓展题没答上来,错失了机会,后来把题目想明白了,给出此题解。