简单来说就是找出最长不重复子串。比如abcb
的最长不重复子串是abc
,bbb
的最长不重复子串是b
题解
1. O(N2)的解法
第一时间想到的就是这种,还是太弱。。。
思路是对于每个位置,都以它为子串的起点向后遍历一次,遇到有重复的就break,然后返回最长的那个。用一个hash表来记录有没有访问过。
int lengthOfLongestSubstring(char* s)
{
int ans = 0;
for(int i = 0;s[i] != ' ';i ++)
{
bool hash[200] = {false};
int count = 0;
for(int j = i;s[j] != ' ';j ++)
{
if(!hash[s[j]])
{
hash[s[j]] = true;
count ++;
}
else
break;
}
ans = ans > count ? ans : count;
}
return ans;
}
2. O(N)的解法
参考了这篇介绍,虽然是英文但是感觉写得很思路很清晰的样子。希望有一天我的思路也能如此清晰。
思路是利用一个额外的空间来保存已经访问过的字符的位置。
首先从左到右扫描整个字符串,同时记录目前所遇到的最长不重复子串
,记它的长度为max_len
.当扫描的时候,对于每一个遇到的新字符,首先判断它有没有被访问过(利用一个visited
数组来判断),如果没有,那么直接把max_len
的长度加1,然后将这个字符标记为访问过,同时记录它的位置。如果之前被访问过,那么就有下面两种情况:
- 这个被访问过的字符不是目前
最长不重复子串
的一部分。这时候直接把max_len
加1,然后将这个字符之前记录的位置改为现在这个位置就可以了 - 如果它是目前的
最长不重复子串
的一部分,那么新的最长不重复子串
就要从这个之前被访问过的字符的下一位开始,这时候要更新max_len
,也要更改这个字符的位置记录。
int max_len = 0,start_max_len = 0,ans = 0;
int index[130] = {0};
bool visited[130] = {false};
for(int i = 0;s[i] != ' ';i ++)
if(!visited[s[i]])
{
visited[s[i]] = true;
index[s[i]] = i;
max_len ++;
ans = ans > max_len ? ans : max_len;
}
else
{
if(index[s[i]] < start_max_len)
{
index[s[i]] = i;
max_len ++;
ans = ans > max_len ? ans : max_len;
}
else
{
start_max_len = index[s[i]] + 1;
max_len = i - start_max_len + 1;
ans = ans > max_len ? ans : max_len;
index[s[i]] = i;
}
}
return ans;