LINK:https://oj.leetcode.com/problems/longest-substring-without-repeating-characters
Solution:https://github.com/haoel/leetcode
Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.
求最长非重复子串,其关键在于重复开始处,一般思路:
遍历字符串,寻找当前字符movePos指向"abcabcbb"在其后重复位置记以lastRepeatPos,指向"abcabcbb",依次判断b在其后重复位置,如b的位置newPos < lastRepeatPos,更新lastRepeatPos,否则不变,依次为c的判断,当前位置movePos+1 = lastRepeatPos时,"abcabcbb",lastRepeatPos为第一个非重复子串的长度"abc",依次最长非重复子串为"bca","cab","abc";
class Solution {
public:
int findRepeatPos(int ind, string s){
for(size_t i=ind+1; i<s.size(); i++)
if(s[ind] == s[i]) return i;
return -1;
}
int findLongestSubstring(string s)
{
int movePos = 0, LastRepeatPos = s.size();
for(size_t i=0; i < s.size() && movePos <= LastRepeatPos; i++){
int repeatPos = findRepeatPos(i, s);
if(repeatPos!=-1 && repeatPos < LastRepeatPos) LastRepeatPos = repeatPos;
if(i + 1 == LastRepeatPos) return LastRepeatPos;
}
return LastRepeatPos;
}
int lengthOfLongestSubstring(string s) {
int longest = 0;
for(size_t i=0; i<s.size(); i++) {
int len = findLongestSubstring(s.substr(i, s.size()-i));
if(longest < len) longest = len;
}
return longest;
}
};
继续优化算法:其实这是一个遍历非重复子串部分的过程,并记录下最长子串的长度。
遍历非重复部分过程中,只需要知道当前字符是否在之前出现过,如果出现了则需要重新开始最长非重复子串的计数。在字符串"abcabcbb"中,lastRepeatPos从-1计数,意指非重复子串的开始位置,movePos指当前字符,判断当前字符是重复出现,如果在非重复子串的开始lastRepeatPos后出现过,即非重复开始的位置lastRepeatPos < movePos,重置lastRepeatPos至movePos曾经出现过的位置,如果没有出现过,即lastRepeatPos > movePos即可获得一非重复子串的长度,如果比记录下来的非重复子串长度还长,替换其。
该部分代码为
function lengthOfLongestSubstring(string s)
for (i=0; i<s.size() ;i++)
{
if(s[i] repeat again and lastRepeatPos < REPEAT_POS[s[i]])
lastRepeatPos = REPEAT_POS[s[i]];
else
cur_len = i-lastRepeatPos;
}
如何保存出现过的字符的位置,利用map的特性map<key_char, value_pos>,key_char保存出现过的字符,value_pos保存字符位置。
或者使用字符位置数组:
const int MAX_CHAR = 256;
REPEAT_POS[MAX_CHAR];
class Solution {
public:
int lengthOfLongestSubstring(string s) {
map<char, int> m;
int maxLen = 0;
int lastRepeatPos = -1;
for(int i=0; i<s.size(); i++){
if (m.find(s[i])!=m.end() && lastRepeatPos < m[s[i]]) {
lastRepeatPos = m[s[i]];
}
if ( i - lastRepeatPos > maxLen){
maxLen = i - lastRepeatPos;
}
m[s[i]] = i;
}
return maxLen;
}
};