不含重复元素的最长子串
思想:
1:初始化 left = right = 0,把索引闭区间 [left, right] 称为一个「窗口」。
2:先不断地增加 right 指针扩大窗口 [left, right],直到窗口中的字符串包含重复的字符串
3:此时转而不断增加 left 指针缩小窗口 [left, right],直到窗口中的字符串不包含重复的字符串。
4:重复2,3,直到 right指针到达字符串 S 的结尾
这里面要涉及-----查找表的增加和删除
代码实现:
#include<iostream> #include<vector> #include<set> #include<string> using namespace std; class soluction{ public: int lengthOfLongestSubstring(string s){ //初始化变量 int lp=0,rp=0;//左右指针指向第一个元素 int curLength=0,maxLength=0;//一个记录当前滑动窗口长度,一个记录待返回最大值 //定义set查找表 set<char> ss;//注意这里是单个字符 //具体实现 while(rp<s.length()){//右指针遍历完字符串后,程序结束 if(ss.find(s[rp])==ss.end()){//右指针指向字符不在查找表set中 ss.insert(s[rp]); //更新curLength和maxLength curLength++; if(maxLength<curLength) maxLength=curLength; rp++;//右指针右移动 } else{//需要左指针右移,直至没有重复元素 while(ss.find(s[rp])!=ss.end()){ ss.erase(s[lp]);//查找表删去左指针 //更新变量 curLength--; lp++; } //此时窗口没有右指针元素 ss.insert(s[rp]); rp++; curLength++; /* 该种情况不必更新maxLength,一定小于curLength */ } } return maxLength; } };
另解:
#include<iostream> #include<vector> #include<set> #include<algorithm> #include<string> using namespace std; class soluction{ public: int lengthOfLongestSubstring(string s){ int lp=0,rp=0;//左右指针指向第一个元素 int maxLength=0;//记录待返回最大值 set<char> m; for(;rp<s.length();rp++){ while(m.find(s[rp])!=m.end()){ m.erase(s[lp]); lp++; } m.insert(s[rp]); maxLength=max(maxLength,rp-lp+1); } return maxLength; } }; int main(){ string s="asdfgasedsaf"; cout<<soluction().lengthOfLongestSubstring(s); return 0; }
代码简化了很多,其实就是把缩小窗口的步骤提前,然后每次在增大窗口的过程中,更新变量
int lengthOfLongestSubstring(string s){ int lp=0,rp=0;//左右指针指向第一个元素 int maxLength=0;//记录待返回最大值 set<char> m; while(rp<s.length()){ /*需要缩小窗口的操作--查找表存在了s[rp]*/ while(m.find(s[rp])!=m.end()){ m.erase(s[lp]);//删左指针对应元素 lp++;//左指针右移 } /*增大窗口的操作*/ m.insert(s[rp]); maxLength=max(maxLength,rp-lp+1); rp++; } return maxLength; }