提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
记录学习每一天,2023.1.12 (3. 无重复字符的最长子串)
一、题目
给定一个字符串 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 由英文字母、数字、符号和空格组成
二、分析和实现
1.递归实现
从初始位置开始遍历,把值保存在hashSet中,判断之前是否有出现过,未包含该值,长度自加1,否则退出循环,判断长度和函数之前传来的长度进行对比,当前长度大于之前长度则替换,判断长度是否大于传来的字符串长度,大于就退出,否则就调用本身,传入当前最大长度和字符截取开始下标加一到结束的字符传入下一层。这方法显然耗时耗力,于是想到了窗口滑动的算法。
public static int recursion(String s, int max) {
// 判断长度
if (s.length() == 0 || s.length() == 1) {
if (s.length() > max) {
return s.length();
} else {
return max;
}
}
int temp = 0;
// 不重复
HashSet<Object> strings = new HashSet<>();
for (int i = 0; i < s.length(); i++) {
if (strings.contains(s.charAt(i))) {
break;
} else {
// 不存在自加1
++temp;
strings.add(s.charAt(i));
}
}
// 判断是否大过上一层传来的值
if (max < temp) {
max = temp;
}
if (max > s.length()){
return max;
}
int recursion = recursion(s.substring(1), max);
if (max < recursion) {
max = recursion;
}
return max;
}
2.滑动窗口算法实现
具体代码如下:
public static int lengthOfLongestSubstring(String s) {
// 记录字符上一次出现的位置
int[] last = new int[128];
int res = 0;
int start = 0; // 窗口开始位置
for(int i = 0; i < s.length(); i++) {
int index = s.charAt(i);
// 获得开始位置
start = Math.max(start,last[index]);
// 当前字符出现的下一个位下标
last[index] = i+1;
// 判断当前位置减去开始位置的值是否大于之前的连续值
res = Math.max(res,i-start+1);
}
return res;
}
总结
学习使人快乐