前言
正文
题目
未看题解时,解题的思路
- 我的想法是做一个map表,记录一下从每个位置出现的次数。相当于,用两次循环去做这件事情。算是暴力解法的一种。
自己实现的代码
code
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.size()==0)
return 0;
if(s.size()==1)
return 1;
map<char,int> map;
for(int i = 0;i<s.size();i++)
{
map[s[i]] = 0;
}
int res = 0;
int maxValue = 0;
bool flag = true;
for(int i = 0;i<s.size();i++)
{
for(int j = i;j<s.size();j++)
{
if(map[s[j]]>0)
{
maxValue = max(maxValue,res);
res = 0;
flag = false;
}
else
{
map[s[j]]++;
res++;
flag = true;
}
}
if(flag)
{
maxValue = max(maxValue,res);
res = 0;
}
for(int i = 0;i<s.size();i++)
{
map[s[i]]=0;
}
}
return maxValue;
}
};
可能实际是过了吧~但是超时了。我使用了O(N^2)的时间复杂度比较糟糕。
看了题解后解题的思路
- 使用滑动窗口的思路,就是有两个指针,一个管理最右边,一个管理最左边,然后每次就检查这个滑动窗口的大小有没有变大就可以 了。从i—>rk+1-i这个大小,就是滑动窗口的大小。
标准答案的代码1
code
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_set<char> uSet;
int rk = -1,res = 0;
for(int i = 0;i<s.size();i++)
{
if(i!=0)
uSet.erase(s[i-1]);
while(rk+1<s.size()&&!uSet.count(s[rk+1]))
{
uSet.insert(s[rk+1]);
rk++;
}
res = max(res,rk+1-i);
}
return res;
}
};
优化的方法
就是当每一次收缩左边的指针时,可以直接收缩到那个重复元素的下一个元素。但要注意,那些被跳过的元素,其实是还在缓存表中,要判断说只有索引号大于那个重复元素的下一个元素的时候,左指针才进行移动。