求字符串中最长无重复字符子串长度
前言
本文介绍一道算法题,求字符串中最长无重复字符子串长度。
正文
题目描述:
给出一个字符串,求字符串中最长无重复字符子串长度。
示例:给出字符串abcdefggddabccef
,其中最长子串为abcdefg
,长度为7
。
注意,子串是指一个字符串中连续的字符组合,不能跳跃字符进行组合。
思路解析
示例给出的字符串abcdefggddabccef
包含连续的子串有abcdefg
、gd
、dabc
、cef
等,其中最长的为abcdefg
。
看到这类的题目之后,第一反应就是从左到右遍历字符串,找最大值即可,过程如下:
- 从下标
0
开始往左对比,记录不重复字符的个数,此时只有a
字符,记录max=1
。 - 从下标
1
开始往左对比,记录不重复字符的个数,此时有ab
字符,记录max=2
。 - 从下标
2
开始往左对比,记录不重复字符的个数,此时有abc
字符,记录max=3
。 - 以此类推,直到遍历到最后,找出最大值即可。
在遍历的时候,不是从某个位置一直往左对比,一直到头的,只要对比到该字符上次出现的位置即可,因此对比终止需要两个因素:
- 当前字符上次出现的位置
- 当前字符前一个位置已经记录的距离
这两个因素产生的位置,那个小,就是本次遍历产生的距离,由这个产生的结果和之前的结果对比,如果是大的则更新最大值。
如上图所示,第22
位置的a
虽然距离第11
位置的a
很远,但是中间有两个s
重复了,所以22
位置的a只能记录距离为5
。
代码实现
根据上面思路分析,来看下代码实现:
public int lengthOfLongestSubstring(String s) {
if (s == null || s.equals("")) {
return 0;
}
char[] str = s.toCharArray();
int[] map = new int[128];
for (int i = 0; i < 128; i++) {
map[i] = -1;
}
map[str[0]] = 0;
int N = str.length;
int ans = 1;
int pre = 1;
for (int i = 1; i < N; i++) {
int cur = Math.min(i - map[str[i]], pre + 1);
ans = Math.max(ans, cur);
map[str[i]] = i;
pre = cur;
}
return ans;
}
声明一个长度为128
的数组是因为ASCII
码只有128
个,足以表示所有的字符了。
根据思路分析里的两个因素分析,可以看到两个因素参数的结果:
i - map[str[i]]
当前元素距离上一个元素的距离pre
表示上一个元素计算的结果,在pre
基础上加上1
就是本次计算的结果
在计算出本次产生的子串长度后,要把本次字符出现的位置更新到map
数组中,以便后面再次出现对比使用,每次循环结束后,要把cur
赋值给pre
,也就是更新上一次计算的结果。
这两个因素产生的结果的最小值就是本次计算的结果,拿到这个结果后,再和之前计算的结果ans
对比,这两个中的最大值,就是循环遍历到i
位置的最长子串的长度值。
在力扣上跑一下看看,打败了100%
哈哈~
总结
本文介绍一道算法题,求字符串中最长无重复字符子串长度,关于本题的解法有很多,例如:动态规划、滑动窗口、暴力循环等,本题相对比较简单,这里就不再做过多介绍了。
转载自:https://juejin.cn/post/7231932125254041659