LeetCode 查找无重复字串时间复杂度问题
今天做到LeetCode的第三题,
给定一个字符串,找出不含有重复字符的 最长子串 的长度。
示例:
给定 "abcabcbb"
,没有重复字符的最长子串是 "abc"
,那么长度就是3。
给定 "bbbbb"
,最长的子串就是 "b"
,长度是1。
给定 "pwwkew"
,最长子串是 "wke"
,长度是3。请注意答案必须是一个子串,"pwke"
是 子序列 而不是子串。
万般WA之后
本以为AC,不知竟然是RE
看了相关文章之后复杂度太高了 原代码如下复杂度近乎为O(n^2)
class Solution
{
public:
int Find(char c,int i,int j,string s);
int lengthOfLongestSubstring(string s)
{
int MAX = 0;
for(int i = 0;i < s.size();i++)
{
int number = 1;
for(int j = i;j < s.size()-1;j++)
{
if(Find(s[j+1],i,j,s)==-1) number++;
else break;
}
if(MAX<number) MAX = number;
}
return MAX;
}
};
int Solution::Find(char c,int i,int j,string s)
{
for(int a = i;a <= j;a++)
{
if(c==s[a]) return a;
}
return -1;
}
优化后:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int i = 0, j = 0;
int n = s.length();
int maxLen = -1;
bool exists[256] = { false };
while (j < n)
{
if (exists[s[j]])
{
maxLen = max(maxLen, j - i);
while (s[i] != s[j])
{
exists[s[i]] = false;
i++;
}
i++;
}
else
{
exists[s[j]] = true;
}
j++;
}
// 考虑"abcd",j遍历完字符串之后,maxLen在while循环中并没有更新,需要在循环外更新一次
maxLen = max(maxLen, j - i);
return maxLen;
}
};
主要思想在于一次遍历
例子“abcdbe"
第一种方法在j遇到b,获得重复信息,所以将i++,j = i;如果重复的是第一个字母,两者一样,但往往并不是这样
所以这是多余的,
第二种在j遇到b时,只变动i = 'c'的位置,而j继续++,复杂度为O(n)
因为如果i只是++,那么必然遇见第二个'b'还是会重新来一遍,这显然是多于的