1.题目链接:**. - 力扣(LeetCode)**
2.题目描述:
给定一个字符串
s
,请你找出其中不含有重复字符的 最长子串的长度。示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。示例 2:
输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。提示:
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成
3.解法一(暴力求解)(不会超时,可以通过):
算法思路:
枚举「从每一个位置」开始往后,无重复字符的字串可以达到什么位置。找出其中长度最大的即可。
再往后寻找无重复字串能到达的位置时,可以利用「哈希表」统计出字符出现的频次,并判断什么时候字串出现了重复元素。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int ret = 0;//记录结果
int n = s.length();
//1.枚举从不同位置开始的最长重复字串
//枚举起始位置
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
ret = max(ret,j - i + 1);
}
}
// 2. 返回结果
return ret;
}
};
解法二(滑动窗口(同向双指针)):
本题运用到桶排序的思想
算法思路:
研究的对象依旧是一段连续的区间,因此可以继续使用「滑动窗口」思想来优化。 让滑动窗口满足:窗口内所有元素都是不重复的。 做法:右端元素 ch 进入窗口的时候,哈希表统计这个字符的频次:
-
如果这个字符出现的频次超过 1 ,说明窗口内有重复元素,那么就从左侧开始划出窗口,
直到 ch 这个元素的频次变为 1,然后再更新结果
-
如果没有超过 1,说明当前窗口没有重复元素,可以直接更新结果
C++算法代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int hash[128] = {0};
int left = 0,right = 0;
int ret = 0;
int n = s.size();
while(right < n){
//进窗口
hash[s[right]]++;
//判断
while(hash[s[right]] > 1){
hash[s[left++]]--;//出窗口
}
//更新结果
ret = max(ret, right - left + 1);
right++;
}
return ret;
}
};