这种类型题第一次做,还是花了比较长的时间的,一共写了两三个版本才写出比较快的方法
1、最后的方法:44ms左右,使用滑动窗口,创建左右两个“指针”,一个哈希表保存<字母,字母在字符创中的索引>,如果后面发现有重复了,就把重复的字母之前都删除掉,改变这个字母的哈希表的值,改变左指针位置。好的测试案例有:“abcbacbb”,“dvdf”,“”,“vdsdf”
#include <list>
#include <algorithm>
#include <set>
#include <queue>
#include <iostream>
#include <string>
#include <stack>
#include <unordered_map>
#include <unordered_set>
using namespace std;
//3. 无重复字符的最长子串
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.size() == 0) {
return 0;
}
unordered_map<char,string::iterator> myHash;
string::iterator itLeft = s.begin();
string::iterator itRight = s.begin();
int MaxLength = -1;
while (itRight != s.end()) {
auto index = myHash.find(*itRight);
if (index != myHash.end()) {
auto temp_pos = index->second + 1;//临时保存一下以后左指针的位置,防止指针瞎指
for (auto i = itLeft; i < index->second; i++) {//把重复的字母之前的字母删除掉
myHash.erase(*i);
}
myHash[*itRight] = itRight;//改一下重复字母本身的索引
//重大问题 ,index已经是空指针了,前面保存起来必须 !本质是个指针的!
//itLeft = index->second;这里一定要注意,引以为戒
itLeft = temp_pos;//改左指针指向的位置
}
else {
myHash[*itRight] = itRight;
}
MaxLength = max(MaxLength, int(itRight - itLeft+1));
//printf("%d\n", int(itRight - itLeft));
itRight++;
}
return MaxLength;
}
};
int main(void) {
Solution solution;
int res = solution.lengthOfLongestSubstring("abcabcbb");
return 0;
}
2、第一个想到的方法:找出 从每一个字符开始的,不包含重复字符的最长子串,两次循环,用了1400+ms,太拉胯了
int lengthOfLongestSubstring(string s) {
if (s.size() == 0) {
return 0;
}
unordered_set<char> charSet;
string::iterator itLeft = s.begin();
int MaxLength = -1;
int CurrentLength = 0;
while (itLeft != s.end()) {
auto itRight = itLeft;
while (itRight != s.end()) {
if (charSet.count(*itRight)) {
//charSet.erase(*itLeft);//左右一样的,不弹也不加
MaxLength = max(MaxLength, CurrentLength);
//CurrentLength--;
break;
}
else {
charSet.insert(*itRight);
CurrentLength++;
}
itRight++;
}
charSet.clear();
MaxLength = max(MaxLength, CurrentLength);
CurrentLength = 0;
itLeft++;
}
return MaxLength;
}
学无止境,天道酬勤