题目:给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
示例1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是"wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke"是一个子序列,不是子串。
算法思路:
- 暴力法:逐个检查所有的子字符串,看它是否不含有重复的字符;算法复杂度0(n^2);
- 借助队列先进先出的属性:遍历字符串的同时判断当前字符是否包含在前面遍历的子字符串中,若存在则依次把队列中的字符串“出列”,直到与当前遍历到的字符相同的字符“出列”为止;若不存在则字符串长度加1,继续遍历。每次遍历的时候要比较记录的最大长度和每个子串的长度,取最大值赋值给最大长度;利用这种思路实现的算法效率不是很高,在leecode官网提交的算法代码执行时间是8ms;
- 滑动窗口:借助队列实现起来比较简单,但增加了创建队列和遍历队列的开销,可以借鉴队列的核心原理实现:只需要记录子串在父串中的索引位置,不借助队列,也不新建字符串,防止增加额外的开销。利用这种思路实现的算法效率比较高,在leecode官网提交的算法代码执行时间是3ms;
算法代码:暴力法的代码比较简单,就不写代码了,感兴趣的可以自己实现一下。
算法代码:根据算法思路2,写出的算法具体代码如下:
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int max = 0;
int curMax = 0;
ArrayDeque<Character> queue = new ArrayDeque<>();
for (int i = 0; i < s.length(); i ++) {
char curChar = s.charAt(i);
if (!queue.contains(s.charAt(i))) {
queue.add(curChar);
curMax ++;
} else {
if (curMax > max) {
max = curMax;
}
char c = queue.remove();
curMax --;
while (c != curChar) {
c = queue.remove();
curMax --;
}
queue.add(curChar);
curMax ++;
}
}
if (curMax > max) {
max = curMax;
}
return max;
}
算法代码:根据算法思路3,写出的算法具体代码如下:
public int lengthOfLongestSubstring(String s) {
int max = 0; // 最长子串的长度
int curMax = 0; // 记录当前遍历的子串长度
int index = 0; // 记录已遍历的重复元素的位置
char curChar;
boolean contain = false;
for (int i = 0; i < s.length(); i ++) {
curChar = s.charAt(i);
int j;
for (j = index; j < i; j ++) {
if (s.charAt(j) == curChar) {
contain = true;
break;
}
}
if (!contain) {
curMax ++;
if (curMax > max) {
max = curMax;
}
} else {
curMax = i - j;
index = j + 1;
contain = false;
}
}
return max;
}
如果你有疑问或更好的算法思路,欢迎留言交流!!!
如果感觉我的文章对您有所帮助,麻烦动动小手给个喜欢,谢谢!!!