无重复字符的最长子串
一、题目
给定一个字符串 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 由英文字母、数字、符号和空格组成
二、代码
代码1:暴力求解
复杂度 O ( n 3 ) O(n^3) O(n3),执行运行超过6.84%用户,内存消耗超过82.01%用户
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.empty())return 0;
if(s.size()==1)return 1;
vector<int> num(s.size(), 0);
for(int i=0;i<s.size();i++){
bool repeat=false;
for(int j=i+1;j<s.size();j++){
for(int k=i;k<j;k++){
if(s[k]==s[j]){
repeat=true;
num[i]=j-i;
break;
}
}
if(repeat)break;
else num[i]=j-i+1;
}
}
sort(num.begin(),num.end());
return num[num.size()-1];
}
};
代码2:力扣用户题解
复杂度
O
(
n
)
O(n)
O(n),执行运行超过98.32%用户,内存消耗超过82.32%用户
思路:
- 滑动窗口,保证每个窗口里字母都是唯一的
- 使用 vector m 来记录一个字母如果后面出现重复时,i 应该调整到的新位置 21. 所以每次更新的时候都会保存 j + 1 ,即字母后面的位置。
- j 表示子串的最后一个字母,计算子串长度为 j - i + 1。
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
vector<int> m(128, 0);
int ans = 0;
int i = 0;
for (int j = 0; j < s.size(); j++) {
i = max(i, m[s[j]]);
m[s[j]] = j + 1;
ans = max(ans, j - i + 1);
}
return ans;
}
};
- 作者:Ikaruga
- 链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters/
个人理解:题解中最重要的点时针对左边界i的设计,i的动作主要为两部分,一个是子串无重复时候i保持原位置,j继续向后扫描;二是当扫描到第j个元素的数与前边出现重复时,i定位到前一个重复元素的之后,如此循环,实现滑动窗口。
三、本题值得注意的点
- 针对此题,滑动窗口无疑是一个复杂度各方面较小的解决方案。
- max()或者min()函数复杂度为 O ( 1 ) O(1) O(1),值得被多次使用。
四、总结
本题主要针对运行时间考察,滑动窗口的方法可大大减少复杂度,进而实现最优求解。