Given a string, find the length of the longest substring without repeating characters.
Examples:
Given "abcabcbb"
, the answer is "abc"
, which the length is 3.
Given "bbbbb"
, the answer is "b"
, with the length of 1.
Given "pwwkew"
, the answer is "wke"
, with the length of 3. Note that the answer must be a substring, "pwke"
is a subsequence and not a substring.
题解:
设置left来标定现无重复字母的字符串的开始位置,i 表示遍历的位置,则无重复字母的最大子字符串的长度为 i - left + 1, 字典中存储的是字母与其对应的字符串的位置(以0为起始点)。变量res存储当前无重复字母的最大子字符串长度。需要注意的是这里不是先确定无重复字母的最大子字符串再求得其长度,而是确定每一个无重复字母的子字符串,求其长度,然后再与保存的最大长度作比较。相当于用一个数组不断的存储每一个无重复字母的字符串的长度,遍历完之后再从这些长度中取最大值作为结果,这里只不过是简化了操作,利用缓存记录上一无重复字母的子字符串的长度,然后不断与现无重复字母的子字符串的长度作比较,取最大值。所以,遇到区间类问题的最大最小值,可以先求得满足条件的所有情况,同时记录这些情况下的最大最小值结果,然后再对比这些结果取最大最小,或者用res = max(res, 现结果)来简化程序。
鉴于此题针对的字符串,可以建立一个数组来模拟字典,如果再遍历过程中map[s[i]]不等于-1, 说明此字母在 i 之前出现过:1. map[s[i]]<left, 说明之前的字母已经不在现非重复字符串中,所以仍然计算字符串长度。2. map[s[i]] >= left, 说明此字母在现字符串中已经出现过一次,则需要调整left的位置,具体调整为此字母上一次出现位置的下一位置,即left = map[s[i]] + 1;
class Solution {
public:
int lengthOfLongestSubstring(string s) {
vector<int> map(, -);
int res = , left = ;
for (int i = ; i < s.size(); ++i) {
if (map[s[i]] == - || map[s[i]] < left) {
res = max(res, i - left + );
} else {
left = map[s[i]] + ;
}
map[s[i]] = i;
} return res;
}
};
利用set,把出现过的字符都放入set中,遇到set中没有的字符就加入set中并更新结果res,如果遇到重复的,则从左边开始删字符,直到删到重复的字符停止
class Solution {
public:
int lengthOfLongestSubstring(string str) {
set<char> s;
int res = , left = ; for (int i = ; i < str.size(); ++i) {
if (s.find(str[i]) == s.end()) {
s.insert(str[i]);
res = max(res, i - left + ); // 也可以写作 res = max(res, (int)s.size()),此时的set中即是当前无重复字母的子字符串
} else {
s.erase(str[left++]);
--i;
}
} return res;
}
};