给定一个字符串 s
,请你找出其中不含有重复字符的 最长 子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc"
,所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成
这题使用滑动窗口,定义start和end,初始化为0,然后固定start移动end,判断map中是否存在该键,若存在,则需要更新当前的start位置,怎么更新呢?如果简单思考,很容易得到应该要把start移动到上一次该重复字符出现的位置+1,但是,if (map.containsKey(s.charAt(end))),当这个条件成立时,并不代表此时的[start, end]区间内的字符串有重复字符,所以此时需要判断重复的字符是否在这个区间内,如果在这个区间内,那么map.get(s.charAt(end)) + 1肯定大于start,所以此时start要更新为map.get(s.charAt(end)) + 1,而如果start大于map.get(s.charAt(end)) + 1,则说明此时[start, end]区间内的字符串没有重复字符,所以start不用更新。然后在计算此时的res,再将当前字符加入到map中。
class Solution {
public int lengthOfLongestSubstring(String s) {
int res = 0;
Map<Character, Integer> map = new HashMap<>();
for (int start = 0, end = 0; end < s.length(); end++) {
if (map.containsKey(s.charAt(end))) {
start = Math.max(start, map.get(s.charAt(end)) + 1);
}
map.put(s.charAt(end), end);
res = Math.max(end - start + 1, res);
}
return res;
}
}
时间复杂度为O(n)。