Given a string, find the length of the longest substring without repeating characters.
Examples:
Given "abcabcbb"
, the answer is "abc"
, which the length is 3.
Given "bbbbb"
, the answer is "b"
, with the length of 1.
Given "pwwkew"
, the answer is "wke"
, with the length of 3. Note that the answer must be a substring, "pwke"
is a subsequence and not a substring.
之前的方法是依次算出下标0~s.size()开始的符合条件的最大窗口长度,返回其中最大的,效率太低。
看了discuss后,照着大神的思路学习了一个,不再依次计算所有元素开头的情况,而是每次从重复的地方开始计算符合条件的最大窗口长度。
思路如下:
- 建立字典dict记录字符在s中出现的位置,用-1初始化,用begin表示窗口开始位置
- 遍历s,如果dict中没有当前字符或者当前字符未在当前窗口出现过,begin不变,否则更新为dict中记录的位置,即将begin更新为max((dict[s[i]] + 1, begin))
- 每次循环都要更新dict和maxlen
- 返回结果
之前的代码:
class Solution {
public:
int lengthOfLongestSubstring(string s)
{
int maxlen = 0;
int len = 0;
int begin = 0;
int end = 0;
unordered_map<int, int> dict;
while (end < s.size())
{
while (dict[s[end]] == 0 && end < s.size())
{
++dict[s[end]];
++end;
++len;
}
maxlen = max(maxlen, len);
if (end < s.size())
{
--dict[s[begin]];
++begin;
--len;
}
}
return maxlen;
}
};
效率更高的代码:
class Solution {
public:
int lengthOfLongestSubstring(string s)
{
vector<int> dict(256, -1);
int maxlen = 0;
int begin = 0;
for (int i = 0; i < s.size(); ++i)
{
begin = max(dict[s[i]] + 1, begin);
dict[s[i]] = i;
maxlen = max(maxlen, i - begin + 1);
}
return maxlen;
}
};