LeetCode - 无重复字符的最长子串
LeetCode -无重复字符的最长子串
废话不多说,先上LeetCode地址:
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 中文版
https://leetcode.com/problems/longest-substring-without-repeating-characters/ 英文版
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
这里我们再题目的描述中可以获得一个信息就是子序列和子串的概念,子串是必须要连续的,但是子序列可以不连续(由示例三得知)。
我们从问题描述中可以得知,要的是不重复字符的最长子串,那我们如果把已经出现过的字符保存起来,然后当出现重复字符的时候,做一个修改,这个修改是什么呢,就是修改子串的起始位置,所以这个问题的关键就是当出现了重复的字符的时候怎么修改字符起始的位置,那么没出现重复字符的时候,我们应该计算字符串当前位置和起始位置的差,然后和当前最大长度比较,如果当前最大长度大,就覆盖,最后返回最大长度即可。
我们就对一个比较短的字符串作分析吧,首先我们初始化我们的字符串初始位置。如果初始位置用s,当前位置用 i。
初始化起始位置是-1,为什么呢?因为即使我们只有一个字符也应该是1,当前位置是0,所以初始化 -1,保存已经出现的字符的hashMap
第一步:初始化 s = -1 i = 0 当前字符 是 p, map 是p : 0这里0表示出现过的index。
然后比较最大长度,当前最大是0 差值是 1 ,覆盖 所以len =1。
第二步:s 不变, i = 1,当前字符 是 w ,map 是 p : 0 w : 0,比较最大长度和当前差值,差值是2 ,最大长度是1,覆盖,所以len=2。
第三步:这一步是关键,因为这里出现了重复的字符w,这个时候我们是怎么操作的呢?首先,我们应该改变字符串的起始位置,该怎么修改呢?这次出现的重复字符上次出现的位置,这里有一个关键点就是起始位置的字符是不算的,为什么不算呢,因为和当前字符重复了。改变完了起始位置以后,把字符的位置做一个覆盖,所以map = p : 0 w :2 s = 1 i = 2 这里 len = 2,比当前差值1大不覆盖。
第四步:s = 1 i = 3 map = p : 0 w : 2 k : 3,len 和当前差值比较,len=2
第五步:s = 1, i = 4 , map = p : 0 w : 2 k : 3 e : 4,len和当前差值比较 len=3
第六步: 替换s = 2, i = 5 map = p : 0 w : 5 e : 4 ,len 和当前差值比较len=3
最后返回len=3
最后是代码:
public static int lengthOfLongestSubstring(String s) {
//初始化,起始位置和最大长度
int max = 0;
int start = -1;
//初始化已经出现的字符map
Map<Character, Integer> characterIntegerMap = new HashMap<Character, Integer>();
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
//如果出现了字符,而且位置大于起始位置就说明重复了,因为起始位置的字符是不算的。
if (characterIntegerMap.containsKey(chars[i]) && characterIntegerMap.get(chars[i]) > start) {
//先修改起始位置
start = characterIntegerMap.get(chars[i]);
//覆盖字符位置
characterIntegerMap.put(chars[i], i);
} else {
//不重复的字符
characterIntegerMap.put(chars[i], i);
//差值和当前最大值比较
if (i - start > max) {
max = i - start;
}
}
}
//返回结果
return max;
}