问题描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
例子
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
输入: s = "" 输出: 0
思路1:
这道题用到的主要思路就是 滑动窗口。
那什么是滑动窗口呢?
其实就是一个队列,比如例题中的abcabcbb,进入这个队列(窗口)为abc满足题目要求,当再进入a,队列就变成了abca,这时候就不满足要求,所以,我们要移动这个队列。
如何移动?
我们只需要把队列的左边的元素移出就可以了,知道满足题目要求!一直维持这样的队列,找出队列出现最长的长度的时候,求出解!
时间复杂度:O(n)
思路2:
其实和思路1差不多。思路也是滑动窗口。
- 定义一个map集合的数据结构存储<K, V>,其中key值为字符,value值为该字符位置+1,加1表示从字符位置后一个才开始不重复。(散列表)
- 定义不重复子串的开始位置为start(队头),结束位置为end(队尾)。
- 随着end不断遍历向后,会遇到与[start, end]区间内字符相同的情况,此时将字符作为key值,获取其value值,并更新start,此时[start,end区间内不存在重复字符]
- 无聊是否更新start,都会更新其map数据结构和结果result。
代码实现
package HOT100;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class T3 {
public static void main(String[] args) {
String s = "bbbbbb";
int len = lengthOfLongestSubstring(s);
System.out.println(len);
}
public static int lengthOfLongestSubstring(String s) {
// 定义一个HashMap集合,可以看做一个散列表,key用来存储字符 value用来存储下标+1
Map<Character, Integer> hashMap = new HashMap<>();
// 定义一个子串最大长度
int maxLen = 0;
// 首先得到字符串的长度
int strLen = s.length();
// 遍历字符串
for (int start = 0, end = 0; end < strLen; end++) {
// 首先获得当前的字符
char currentChar = s.charAt(end);
// 判断当前字符是否在hashMap中
if (hashMap.containsKey(currentChar)) {
// 找到相同的字符 start需要更新
start = Math.max(start, hashMap.get(currentChar));
}
// 更新当前的 子串 长度
maxLen = Math.max(end - start + 1, maxLen);
// 存储到集合中 注意:这里是end+1
hashMap.put(currentChar, end + 1);
}
return maxLen;
}
}