给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其
长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
思路:
题目需要找出一个子串,它无重复字母且长度最长,输出长度。很容易想到暴力的方法,两层循环找到所有子串,同时再判断他是否存在重复字符串,借助hash表,时间复杂度是你n^3。
优化:上述方法有很多重复计算,eg:1-6中判断是否无重复字母,判断了234是否重复;2-5中又计算了一遍。所以暴力的方法是可以优化的。
设置左右指针,left初始化为0,同时申请一个hashmap(key是字符,val是下标),right指针从0开始向右扫,当s[right]最后一次出现是在left及其右边,则说明当前子串重复了,可以截一段了,算出长度,同时left更新为map.get(s[right])的值,而right指针继续往后就行,这样就利用了先前判断好的结果,不会重复计算;如果不是,则更新map
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null || s.equals(""))
return 0;
int left = 0, len = 0, i = 0, res = Integer.MIN_VALUE;
Map<Character, Integer> map = new HashMap<>();
for (i = 0; i < s.length(); i++) {
char tmp = s.charAt(i);
if(map.containsKey(tmp)){
if(map.get(tmp) >= left){
len = i - left;
if(len > res)
res = len;
left = map.get(tmp) + 1;
}
}
map.put(tmp, i);
}
len = i - left;
return Math.max(len, res);
}
}