Problem: 3. 无重复字符的最长子串
首先我们来分析一下本题的思路
b
,那么最长子序列的长度即为1所以到现在读者应该可以清楚题目到底是要我们做什么,接下去我们就具体地来讲解该如何去求解这个最长子串的长度
马上我们通过两种解法来分析一下该如何去求解本题
首先要给大家介绍的肯定是暴力枚举,不过我们要通过【哈希表】来进行配合,如果对这个数据结构不太了解的话可以看看 一文带你快速入门哈希表
right
用来遍历字符并将其放入哈希表中right
指针不断向后进行遍历的时候,将所遇到的字符全部放入哈希表中,最后当遇到有重复字符的时候,就停下来e
这个位置,然后让right
继续从这个位置开始向后进行移动,那么此时就可以清楚其会遍历到之前所碰到的那个重复的字符a
;很明显,这是多此一举的做法a
,[d, e] 这个区间内并没有这个重复的元素a
,所以呢这个right
指针撑死了只能跑到这个第二次重复的位置left
指针跑过这个重复元素才对,而且这个right
指针不需要再回到当前left
所在位置,而是直接从那个重复元素的位置开始向后遍历即可对于上面的这一种思想,我们就称之为【滑动窗口】
我们来捋一下这个滑动窗口的逻辑:
left
和right
指针同时指向0的位置,遇到字符就往哈希表中放入字符right
超出边界之后,返回最终的那个结果以上就是本题使用滑动窗口进行求解的所有流程,读者可以根据这个思路顺利一遍逻辑,然后试着写写看代码
本题是我们滑动窗口的第二题了,如果有看过上一篇题解的读者应该可以知道对于滑动窗口而言,其代码是差不多的,读者在解决此类问题的时候不仅要知道我们为什么要利用【滑动窗口】去解决本题,而且还需要明白为什么使用【滑动窗口】来解决本题,这样大家在遇到类似题目的时候就可以很快地想到对应的解决策略✔
对于时间复杂度而言,读者在看了以下代码的时候,不要就认为两层循环就是 O ( n 2 ) O(n^2) O(n2),从开始到结束其实
left
和right
指针各自遍历了一遍这个数组,所以最后的时间复杂度即为 O ( n ) O(n) O(n)
没有在堆区上申请任何空间,所以空间复杂度为 O ( 1 ) O(1) O(1)
以下是整体的代码展示
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int n = s.size();
int len = INT_MIN;
int hash[128] = {0}; // 使用数组来模拟哈希表
for(int left = 0, right = 0; right < n; ++right)
{
// 进窗口
hash[s[right]]++;
// 若发现有重复的字符出现
while(hash[s[right]] > 1)
{
hash[s[left++]]--; // 将字符从数组中移除
}
// 更新长度
len = max(len, right - left + 1);
}
return len == INT_MIN ? 0 : len;
}
};