最长不重复的子串问题,这个子串是没有重复字符的,且是连续的。
先看一些例子,有助于我们对这个问题的理解。
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
我们以pwwkew为例,为了控制重复性,我们需要一个map或者set,
在这里,为了删除集合中的某些元素,还想保存index信息,所以,map比较合适。
用pre来标记子串的开始,pre = 0
index 0 : 没有重复,add 'p' to map , map = {'p'}
index 1 : 没有重复,add 'w' to the map , map = {'p', 'w'}
index 2 : w重复了,此时的子串长度 = map.size()
我们想要从index = 2开始,再看看有没有合适的子串。
所以,我们删掉set中的 重复元素(第一个w,index = 1)之前的 'p'元素, (因为它已经不能再构成子串了)
map = {'w'}
pre = 2
index 3 : 没有重复,add 'k' to the map, map = {'w', 'k'}
index 4 : 没有重复, add 'w' to the map, map = {'w', 'k', 'e'}
index 5 : w重复了,但此时重复的w(index = 2,而pre = 2)前面没有需要删除的元素的,map = {'w', 'k' , 'e'};
所以,按照这个思路,算法的时间复杂度为O(n)。
代码:
public int lengthOfLongestSubstring(String s) {
int maxLength = 0;
int pre = 0;
Map<Character, Integer> store = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (!store.containsKey(c)) {
store.put(c, i);
} else {
int index = store.get(c);
maxLength = Math.max(maxLength, store.size());
for (int dIndex = pre; dIndex < index; dIndex++) {
store.remove(s.charAt(dIndex));
}
store.put(c, i); // update the repeating character index
pre = index + 1;
}
}
return Math.max(maxLength, store.size());