题目:
给定一个字符串str,返回str的最长无重复字符子串的长度。
如:"abcd" 返回4 "abcb" 返回3
要求:若字符串的长度为N 算法的时间复杂度为O(N)。
思路:
下面给出的算法 时间复杂度为O(N) 空间复杂度为O(M) 其中 :
N为字符串的长度 M是字符串中字符编码的范围(ASCII码最大值)。
首先定义以下2个变量:
mp<char, int> —— 存储某个字符最近出现的位置。
pre —— 表示遍历到str[i]时 以str[i - 1]字符结尾的情况下最长无重复子串开始的前一个位置。
maxSubLen —— 记录以每个字符结尾的情况下,最长无重复子串长度的最大值。
初始时 pre = -1 maxSubLen = 0
mp[str[i]] 表示遍历完str[0]-str[i-1]后 str[i]字符最近一次出现的位置 设为A。
pre + 1 表示以str[i - 1]字符结尾的情况下 最长无重复子串的开始位置。
讨论:
A > pre 以str[i]结尾的最长无重复子串范围即为: str[A + 1] ~ str[i]
A <= pre 以str[i]结尾的最长无重复子串范围即为: str[pre + 1] ~ str[i]
令:maxEdIdx = max(A, pre);
执行完上述操作后,更新pre【pre 和 A的较大值】 更新maxSubLen【maxSubLen 和 maxEdIdx 的较大值】
重复上述操作,直至所有字符遍历完。
贴代码:
<span style="font-size:12px;">#include <iostream>
#include <string>
using namespace std;
int longestSubstring(string A, int n)
{
int mp[256];
memset(mp, -1, 256 * sizeof(int));
int pre = -1, maxSubLen = 0;
for (int i = 0; i < n; ++i)
{
pre = max(pre, mp[A[i]]);
maxSubLen = max(maxSubLen, i - pre);
mp[A[i]] = i;
}
return maxSubLen;
}
int main(void)
{
string str = "aabcdb";
cout<<longestSubstring(str, str.length())<<endl;
return 0;
}</span>