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.
Subscribe to see which companies asked this question.
最开始直接用从0移动到string尾部,通过定义一个含有256个int数组来统计char的出现与否,好像类似hash,刚开始以为也要返回string,且对拷贝也没多严格限制,得到
class Solution {
public:
int lengthOfLongestSubstring(string s) {
string output = "", s_out = "";
int map[256] = {0};
int length = 0, size = s.size(), temp = 0, len_out = 0;
while (temp < size) {
if (!map[s[temp]]) {
++map[s[temp]];
++length;
output += s[temp];
} else {
if (length > len_out) {
len_out = length;
s_out = output;
}
auto a = output.find(s[temp]);
for (int i = 0; i < a; ++i)
map[output[i]] = 0;
output = output.substr(a + 1) + s[temp];
length -= a;
}
++temp;
}
if (length > len_out) {
len_out = length;
s_out = output;
}
return len_out;
}
};
32ms ac
后面对代码优化,主要减少了不必要的复制操作,并且hash的数组不单单可以记录char是否出现,还能记录出现的位置,这样省去更多条件判断,得到
class Solution {
public:
int lengthOfLongestSubstring(string s) {
auto size = s.size();
string::size_type i = 0, j = 0, len_out = 0, length = 0;
decltype(size) map[256] = {0};
while (i<size && j<size) {
if ( (!map[s[j]]) && ((s[i] != s[j]) || (i == j)) ) {
map[s[j]] = j;
++j;
++length;
}
else {
if (length > len_out)
len_out = length;
for (auto k = i; k < map[s[j]]; ++k)
map[s[k]] = 0;
i = map[s[j]] + 1;
map[s[j]] = j;
length = j - i + 1;
++j;
}
}
if (length > len_out)
len_out = length;
return len_out;
}
};
19ms ac,这里主要一直在纠结
if ( (!map[s[j]]) && ((s[i] != s[j]) || (i == j)) )
这里条件一直写错。。
后面看了题解,发现可以更简单的判断,第二个答案还是需要清零hash数组,假设子串由前后位置分别由下标i,j标记,则我们可以通过判断当前char的hash值是否超过i,如果超过i,则有重复,如果没有,则没重复,这样的话,就不用对hash数组进行清零操作了。。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
auto size = s.size();
int i = 0, j = 0, len_out = 0, length = 0;
vector<int> map(256, -1);
while (j<size) {
if ( map[s[j]] < i) {
map[s[j]] = j;
++j;
++length;
}
else {
if (length > len_out)
len_out = length;
i = map[s[j]] + 1;
map[s[j]] = j;
length = j - i + 1;
++j;
}
}
if (length > len_out)
len_out = length;
return len_out;
}
};
12ms ac 果然更快了。。
最后看到一个9行的答案,整理了一下while里面的条件判断的重复步骤,学着写了一下
class Solution {
public:
int lengthOfLongestSubstring(string s) {
auto size = s.size();
int i = 0, j = 0, len_out = 0;
vector<int> map(256, -1);
while (j<size) {
if ( map[s[j]] >= i)
i = map[s[j]] + 1;
map[s[j]] = j;
len_out = len_out > j - i + 1 ? len_out : j - i + 1;
++j;
}
return len_out;
}
};
25ms ac,主要为了短,省去好多中间变量,因此也得多求好几次值,使得耗时增加。。