整体思路: 用一个unorder_map来保存字符串中每个字符所对应的最近一次出现位置,用字符串本身作为map的key
设一个k和i,k用来表示最长子串的起始位置,i用来表示顺序遍历的当前位置,max_len用来保存当前最长子串长度
遍历字符串
如果当前字符没有出现过(map[key] == 0),则置map的value为当前位置i
如果当前字符已经出现过(map[key] != 0),则首先更新max_len,在将k到上一次出现当前重复字符的位置(map[s1[i]])之间的所有字符对应的value值置为0,表示这些字符在新的子串中没有出现过。
注意: 由于第一个节点的位置i==0,无论访问过还是没有访问过,map中第一个字符所对应的value值一直是0,这会产生误解,到底是这个字符没有遍历过所以为0,还是被遍历过设置成了0。为了解决这个问题,在字符串开头设置一个“#”,这是一个除了开头,不会再出现的字符,避免了重复出现无法判断的问题
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int i, k = 1;
int max_len = 0;
if(s.length() == 0 || s.length() == 1)
return s.length();
string s1 = "#" + s;
unordered_map<int, int> map;
for(i = 0; i < s1.length(); i++){
if(map[s1[i]] != 0){
max_len = max(max_len, i - k);
for(k; k < map[s1[i]]; k++)
map[s1[k]] = 0;
k = map[s1[k]] + 1;
}
map[s1[i]] = i;
}
return max(max_len, i - k);
}
};