3. Longest Substring Without Repeating Characters
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.
主要考察字符串操作。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int locs[256];//保存字符上一次出现的位置
memset(locs, -1, sizeof(locs));
int idx = -1, max = 0;//idx为当前子串的开始位置-1
for (int i = 0; i < s.size(); i++)
{
if (locs[s[i]] > idx)//如果当前字符出现过,那么当前子串的起始位置为这个字符上一次出现的位置+1
{
idx = locs[s[i]];
}
if (i - idx > max)
{
max = i - idx;
}
locs[s[i]] = i;
}
return max;
}
};
》使用i和j两个指针进行搜索,i代表候选的最长子串的开头,j代表候选的最长子串的结尾。
》先假设i不动,那么在理想的情况下,我们希望可以一直右移j,直到j到达原字符串的结尾,此时j-i就构成了一个候选的最长子串。每次都维护一个max_length,就可以选出最长子串了。
》实际情况是,不一定可以一直右移j,如果字符j已经重复出现过(假设在位置k),就需要停止右移了。记录当前的候选子串并和max_length做比较。
接下来为下一次搜寻做准备。
》在下一次搜寻中,i应该更新到k+1。这句话的意思是,用这个例子来理解,abcdef是个不重复的子串,abcdefc中(为了方便记录为abc1defc2),c1和c2重复了。那么下一次搜寻,应该跨过出现重复的地方进行,否则找出来的候选串依然有重复字符,且长度还不如上次的搜索。所以下一次搜索,直接从c1的下一个字符d开始进行,也就是说,下一次搜寻中,i应该更新到k+1。
LeetCode给出的参考答案:
int lengthOfLongestSubstring(string s) {
int n = s.length();
int i = 0, j = 0;
int maxLen = 0;
bool exist[256] = { false }; //各种字符的ASCII码范围是从0-255,共256个
while (j < n) {
if (exist[s[j]]) { //如果现在检测的字符已经存在过了
maxLen = max(maxLen, j-i); //更新最大不重复长度
while (s[i] != s[j]) { //为下一轮不重复子字符串检测做准备,将之前存的已存在字符设为不存在
exist[s[i]] = false;
i++;
}
i++;//子字符串开始指针后移一位
j++; //尾指针后移,继续检测
} else { //如果当前的字符还没有出现过,那么,把它加入已存在字符中,更新已存在字符表
exist[s[j]] = true;
j++; //并将尾指针后移
}
}
maxLen = max(maxLen, n-i);
return maxLen;
}
时间复杂度是O(N)。虽然有两个while的嵌套,但是时间复杂度依然是O(N),