Num 3 无重复的最长子串
最简单做法:暴力二重循环,tle
优化:只走一次,每次两个标记左右,如果出现重复的,把left调整到第一个不重复的位置,每次得出的子串和最长的比较
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Solution { public: int lengthOfLongestSubstring(string s) { if(!s.length()) return 0; int left=0; int ans=1; for(int i=1;i<s.length();i++) { int j=i-1; while(j>=left && s[j]!=s[i]) j--; left=j+1; ans=max(ans,i-left+1); } return ans; } };
这样的优化本质上还是二重循环,仅仅比原来的暴力二重循环省略了一部分过程。
偶然发现自己很久之前写过一个、方法差不多,用的ascii对应bool直接判断有无重复,时间更短内存近似
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Solution { public: int lengthOfLongestSubstring(string s) { int len=s.length(); int first,end; int ans=0; int now=0; first=0; int i,j; end=0; bool pd[300]; memset(pd,0,sizeof(pd)); for(i=0;i<len;i++) { if(pd[s[i]]==false) { now++; end++; pd[s[i]]=true; //cout<<"do1"<<s[i]<<" "<<first<<" "<<end<<endl; } else { if(now>ans) ans=now; while(s[first]!=s[i]) { pd[s[first++]]=false; now--; } first++; now--; now++; end++; pd[s[i]]=true; //cout<<"do2"<<s[i]<<" "<<first<<" "<<end<<endl; } } if(now>ans) ans=now; return ans; } };
注意空字符串的处理过程
最上面的代码是用的滑窗法,但是寻找重复的过程还是要找一遍,用map也是一样的。
在很久以前写的这个里面,用bool省略了一部分查询过程,只需要在发现重复的时候回去找。
为了更快,可以直接用int数组标记出现位置,节省查询时间。
map更适合范围更大的东西,如果范围明确用数组更合适。这里面限制了都是数组,开够ascill对应的字符就ok。数组是o(1),map是o(logN),向上面的直接查询是o(n)
总结
基础优化<很久前写的bool标记有无<map标记位置<数组标记位置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Solution { public: int lengthOfLongestSubstring(string s) { int a[200]; if(!s.length()) return 0; int ans=1; int left=0; memset(a,-1,sizeof(a)); for(int i=0;i<=s.length()-1;i++) { if(a[s[i]]==-1) { a[s[i]]=i; } else { ans=max(ans,i-left); for(int j=left;j<a[s[i]];j++) a[s[j]]=-1; left=a[s[i]]+1; a[s[i]]=i; } } int temp=s.length()-1-left+1; ans=max(ans,temp); return ans; } };
最终优化版