力扣题目链接:无重复字符的最长子串
一、题目解析
二、算法原理
解法一:暴力解法(时间复杂度最坏:O(N))
从每一个位置开始往后枚举,在往后寻找无重复最长子串时,可以利用哈希表来统计字符出现的频率,如果出现了重复字符就跳出循环,如果没有重复则更新结果,这样枚举下去找到长度最长的返回即可。
解法二:滑动窗口
滑动窗口也是定义了两个指针在移动,但是这两个指针所指向的区间就像一个滑动的窗口一样。
滑动窗口的基本步骤
- 定义两个指针int left=0,right=0;
- 进入滑动窗口——>让字符进入哈希表
- 判断条件——>窗口内出现重复字符
- 出滑动窗口——>从哈希表中将字符删除
- 更新结果
注:结果的更新不一定是放在最后,这个要根据题目的要求进行相应的改变,而且判断条件是要循环一直判断,如果满足就出窗口,不满足条件循环才停止。
每次移动指针的时候结果都在更新,所以结果不会出错。
时间复杂度:虽然代码是两层循环,但是left指针和right指针都是不回退的,两者最多都往后移动n次。因此时间复杂度是O(N)。
这个题最大的难度是怎么分析这个问题从而想到要用滑动窗口来解决。
三、代码编写
暴力枚举
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int ret = 0;
int n = s.size();
for(int i = 0; i < n; i++)
{
int hash[128] = {0};//用数组模拟哈希表,统计次数
for(int j = i; j < n; j++)
{
hash[s[j]]++;
if(hash[s[j]] > 1)//判断是否重复
break;
ret = max(ret, j - i + 1);//更新结果
}
}
return ret;
}
};
滑动窗口
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int ret = 0;
int left = 0, right = 0, n = s.size();
int hash[128] = {0};//用数组来模拟哈希表
while(right < n)
{
hash[s[right]]++;//进窗口
while(hash[s[right]] > 1)//判断
{
hash[s[left++]]--;//出窗口
}
ret = max(ret, right - left + 1);//更新结果
right++;
}
return ret;
}
};
如有错误或不足欢迎大家批评指正。