48 最长不含重复字符的子字符串
1 题目描述
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
2 题目分析
思路:动态规划思想:定义f(i)表示以第i个字符为结尾的不包含重复字符的子串最长长度。
初始:f(0) = 1;
转移方程:
-
当i没出现过时,f(i) = f(i - 1) + 1
-
当i出现过,先找到与上一个出现过位置的距离d,判断d和f(i - 1)的长度,如果:d<=f(i - 1),则说明上一个重复位置在当前的最大子长度中f(i) = d,否则说明上一个出现的位置已经与当前的最大子长度无关了,因此f(i) = f(i - 1) + 1
-
输出f(n - 1)
3 代码
public int lengthOfLongestSubstring(String s) {
// 1. 定义两个变量表示当前的最大字串长度和最终的最大子串长度
int curLength = 0, maxLength = 0;
// 2. 用26长度的数组来记录当前字符的上一次出现的索引位置
//int[] position = new int[26];
//Arrays.fill(position, -1);
// 2. 用hashMap来存储当前字符上一次出现的索引位置
Map<Character, Integer> map = new HashMap<>();
// 3. 遍历字符串,进行方程转移
char[] ch = s.toCharArray();
int len = ch.length;
for (int i = 0; i < len; i++) {
// 先判断是否重复或者d和f(i - 1)的大小,即判断position[ch[i]] 是否小于0即可
int preIndex = map.getOrDefault(ch[i], -1);
if (preIndex < 0 || i - preIndex > curLength) {
curLength++; // f(i) = f(i - 1) + 1
} else {
curLength = i - preIndex; // f(i) = d;
}
// 更新maxLength
maxLength = Math.max(maxLength, curLength);
// 将i个元素的位置存放到position中
map.put(ch[i], i);
}
return maxLength;
}