题目传送门【🌀】
前言:力扣3.无重复字符的最长子串,是最经典不过的滑动窗口题
——虽然我的首解是用模拟法解决的q(≧▽≦q)
这也说明了:算法不用生搬硬套,不断尝试、创新挑战才是不二法门✔
关键字索引:滑动窗口、哈希表、模拟法、无重复的最长子串、力扣第三题
题目描述:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
题意补充:
示例1️⃣:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例2️⃣:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例3️⃣:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,
"pwke" 是一个子序列,不是子串。
提示💥:
思路|破解——
A解:将整个过程模拟,即可
思路标识-:
- 1-》找出最长无重复子串的过程并不复杂
- 2-》从前往后,对每个字母判断其之前有无出现,如果没有出现,则当前加上该字母,否则,直接去掉重复字母及其前面的所有字母,从而保证子串无重复字母
- 3-》找到模拟过程中出现的最长无重复子串即可
解题-:
class Solution {
public:
int f(string s,char ch){//定义查找函数
int jie=-1;
for(int i=0;i<s.size();i++){
if(s[i]==ch){
jie=i;
break;
}
}
return jie;
}
int lengthOfLongestSubstring(string s) {
if(s.empty())return 0;
string tmp="";
tmp+=s[0];
int jie=1;
for(int i=1;i<s.size();i++){
if(f(tmp,s[i])==-1){
tmp+=s[i];
}
else{
int k=f(tmp,s[i]);//找到子串中的重复字母
tmp.erase(0,k+1);//去除它和它前面的所有字母
tmp+=s[i];
}
int tp=tmp.size();
jie=max(tp,jie); //更新最大长度
}
return jie;
}
};
B解:经典的滑动窗口
思路标识-:
- 滑动窗口是通过双指针同向移动求解问题的一种方法。但这里的移动需要多点思考
- 1-》快指针在前,对应的慢指针指向子串开头
- 2-》如果快指针对应字母的前一个重复字母位置超过慢指针,说明我们要将慢指针移动到那个重复字母的后一位,以保证滑动窗口里无重复字母
- 3-》从过程中找出出现过的最大长度即可
解题-:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int hash[128]={0};
int jie=0,slow=0;
for (int fast = 0; fast< s.size(); fast++) {
slow= max(slow, hash[s[fast]]);//移动慢指针
hash[s[fast]] = fast + 1;
jie = max(jie, fast - slow + 1);//更新长度
}
return jie;
}
};
知识回顾:
- 对于一些过程简单的题目,可以考虑模拟的思想
- 滑动窗口,窗口两边指针的移动需要依题目而灵活变通,制定正确对策