Given a string s, find the length of the longest substring without repeating characters.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
LeetCode的运行时间很不稳定,最上面的三次使用完全相同的代码,但是结果相差很大,但仍然可以得知,采用数组比map大幅节省时间
更新最优解法:
思路来自于第二高赞
时间复杂度仍是O(N),但是时间大幅减少。
字符的数量有限,可以使用整型数组来代替map
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int last[128];
int left=0;
int maxlength=0;
for(int i=0;i<128;i++){
last[i]=-1;
}
for(int i=0;i<s.size();i++){
int temp=int(s[i]);
if(last[temp]>=0){//判断语句可有可无,对最终结果影响不大
left=max(last[temp]+1,left);
}
last[temp]=i;
maxlength=max(maxlength,i-left+1);
}
return maxlength;
}
};
尝试的最优解法:
思路来自于最高赞评论
时间复杂度O(N)
class Solution {
public:
int lengthOfLongestSubstring(string s) {
map<char,int>m;
int maxlength=0;
int left=0;
for(int i=0;i<s.size();i++){
if(m[s[i]]!=0){
//如果出现在map中,包含两种情况
//left<=m[s[i]]-1,说明重复元素包含在当前字符串中,则最左边的下标更新为重复元素的后一个坐标
//left>m[s[i]]-1,说明重复元素是之前出现的,不需要更新left的值
left=max(m[s[i]],left);
}
m[s[i]]=i+1;//下标从0开始,为了防止和没有映射存在的情况混淆,统一加1
maxlength=max(maxlength,i-left+1);
}
return maxlength;
}
};
解题思路:
使用map记录每个字符是否出现,temp记录当前不重复的字符串。检测到重复的字符,删除temp中重复字符之前的字符,并在map中将对应字符的值置为0.更新最大长度。如果未检测到重复字符,则加在temp后面,map中字符的值置为1,长度加1.
最后再次比较length和longest的大小,取最大值
class Solution {
public:
int lengthOfLongestSubstring(string s) {
map<char,int>m;
int longest=0,length=0;//longest目前为止最大的不重复串;length当前串的长度
string temp="";
for(int i=0;i<s.size();i++){
if(m[s[i]]!=0){
int j;
for(j=0;temp[j]!=s[i];j++){
m[temp[j]]=0;//清除重复字符及其前面的字符
}
if(j==temp.size()-1){
temp="";
}else{
temp=temp.substr(j+1,-1);
}
temp+=s[i];
if(longest<length){
longest=length;
}
length=temp.size();
m[s[i]]=1;//记录出现的位置
}else{
temp+=s[i];
m[s[i]]=1;
length++;
}
}
if(longest<length){
longest=length;
}
return longest;
}
};
参考代码:
滑动窗口
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.size() == 0) return 0;
unordered_set<char> lookup;//无序集合
int maxStr = 0;
int left = 0;
//find的返回值是一个迭代器(iterator),
//如果找到了会返回指向目标元素的迭代器,没找到会返回end()
for(int i = 0; i < s.size(); i++){
while (lookup.find(s[i]) != lookup.end()){
//如果当前元素已经包含在集合里面了,则去掉重合元素之前的元素
//直到把重合的元素去掉,才会结束循环
//left记录当前无重复字符串最左边的下标。先去掉,left向后移动
lookup.erase(s[left]);
left ++;
}
maxStr = max(maxStr,i-left+1);
lookup.insert(s[i]);//把最新的元素加入到集合中
}
return maxStr;
}
};
作者:powcai
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/hua-dong-chuang-kou-by-powcai/
来源:力扣(LeetCode)