3. Longest Substring Without Repeating Characters (Medium)
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.
Solution 1: Sliding Window
The above solution requires at most 2n steps. In fact, it could be optimized to require only n steps. Instead of using a set to tell if a character exists or not, we could define a mapping of the characters to its index. Then we can skip the characters immediately when we found a repeated character.
The reason is that if $$s[j]$$ have a duplicate in the range $$[i,j)$$ with index $$j'$$, we don't need to increase $$i$$ little by little. We can skip all the elements in the range $$[i,j']$$ and let $$i$$ to be $$j' + 1$$ directly.
Complexity Analysis
Time complexity : $$O(n)$$. Index $$j$$ will iteraten $$n$$ times.
Space complexity (HashMap) : $$O(min(m,n)$$. Same as the previous approach.
Space complexity (Table): $$O(m)$$. $$m$$ is the size of the charset.
int lengthOfLongestSubstring(string s) {
vector<int> m(128, -1); // idx
int start = -1, res = 0;
for (int i = 0; i < s.size(); ++i) {
start = max(start, m[s[i]]);
res = max(res, i-start);
m[s[i]] = i;
}
return res;
}
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int i = 0, res = 0;
vector<int> v(128, 0);
for (int j = 0; j < s.size(); ++j) {
i = max(i, v[s[j]]); // new start position
res = max(res, j-i+1);
v[s[j]] = j+1;
}
return res;
}
};
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int res = 0, cnt = 0, start = 0;
vector<int> v(128,-1);
for (int i = 0; i < s.size(); ++i) {
if (v[s[i]] != -1 && start <= v[s[i]]) {
start = v[s[i]]+1;
v[s[i]] = i;
} else {
v[s[i]] = i;
res = max(res, i-start+1);
}
}
return res;
}
};
Solution 2: Hash Table, Two Pointers 19ms
using substring problem template
class Solution {
public:
int lengthOfLongestSubstring(string s) {
vector<int> map(128,0);
int left = 0, right = 0, maxlen = 0, count = 0;
while (right < s.size()) {
if (map[s[right++]]++ > 0) ++count; //invalid
while (count > 0) {
if (map[s[left++]]-- > 1) --count;
}
// valid
maxlen = max(maxlen, right-left);
}
return maxlen;
}
};