题目描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例
示例 1:
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 abc,所以其长度为3。示例 2:
输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 b,所以其长度为 1。示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 wke,所以其长度为3。请注意,你的答案必须是 子串 的长度,pwke 是一个子序列,不是子串。
思路1
利用双指针,也就是滑动窗口的思想,只需要遍历一遍。而unordered_set得删除和添加的时间复杂度为0(1)。
代码
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int n = s.size();
if (n < 2) return n;
unordered_set<char> set;
int maxLength = 0, i = 0, j = 0;
while (i < n && j < n){
if (set.count(s[i]) == 0){
set.insert(s[i++]);
maxLength = max(maxLength, i-j);
}
else set.erase(s[j++]);
}
return maxLength;
}
};
思路2
用数组m来记录字符(字符的大小<256)出现的最新位置,用一个指针left来更新不重复字串的最左位置的前一位置。
举例:s = "abcab"
(1)初始时,left = -1,当前不重复字串的长度res = 0,m初始化为-1
(2)遍历数组,i = 0时,m[a] = 0,即a出现的第一个位置为0,left = -1,res=1;
(3)i = 1时,m[b] = 1,即b出现的第一个位置为1,left = -1,res = 2;
(4)i = 2时,m[c] = 2,即c出现的第一个位置为2,left = -1,res = 3;
(5)i = 3时,此时发现m[a]已经出现过了,位置为0,则更改不重复左指针的位置,left = 0,并且更新a出现的第一次位置,m[a] = 3,此时res = 3;
(6)i = 4时,此时发现m[b]已经出现过了,位置为1,则更改不重复左指针的位置,left = 1,并且更新b出现的第一次位置,m[b] = 4,此时res = 3;
(7)以此类推。。。
代码
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int len = s.size();
if (len < 1)
return 0;
vector<int> m(256, -1);
int left = -1;
int res = 0;
for (int i= 0; i < len; ++i){
left = max(left, m[s[i]]);
m[s[i]] = i;
res = max(res, i - left);
}
return res;
}
};