提示:以下是本篇文章正文内容,下面案例可供参考
-
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
-
示例 1:
- 输入: s = “abcabcbb”
- 输出: 3
- 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
-
示例 2:
- 输入: s = “bbbbb”
- 输出: 1
- 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
-
示例 3:
- 输入: s = “pwwkew”
输出: 3 - 解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
- 输入: s = “pwwkew”
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
提示:
一、滑动窗口 Map解法
- 思路:使用两个指针来定义一个滑动窗口,并且使用map映射来跟踪每个字符的位置,每当遇到重复字符的时候九江开始的指针(startIndex)移动到重复字符的后边,每一步操作都会更新子数的长度
public static int lengthOfLongestSubstringMap(String s) {
//用来存放 s中拆解的每一个字符 跟字符对应的下标
Map<Character, Integer> map = new HashMap<>();
//字符串中字符的长度
int length = s.length();
//无重复最长子数的总和
int sum = 0;
//使用两个指针来定义当前需要考虑的子串
for (int endIndex = 0, startIndex = 0; endIndex < length; endIndex++) {
//获取endIndex指针下标的字符
char str = s.charAt(endIndex);
//检查该字符是否已经存放在该子串当中
if (map.containsKey(str)) {
//重新计算startIndex的指针下表,将startIndex移动到当前字符的最后出现位置的右侧
startIndex = Math.max(map.get(str), startIndex);
}
//使用当前的字串的长度更新sum
sum = Math.max(sum, endIndex - startIndex + 1);
//更新映射
map.put(str, endIndex + 1);
}
return sum;
}
二、滑动窗口 HashSet 解法
- 思路:使用HashSet来进行维护一个滑动窗口的唯一字符,使用两个指针定义窗口的位置,每一步都做判断该字符是否存放在HashSet中,动态来调整窗口的大小,更新最长的子串
public static int lengthOfLongestSubstringSet(String s) {
//字串长度
int length = s.length();
int sum = 0;
HashSet<Character> charSet = new HashSet<>();
//使用开始跟结束的指针定义一个窗口
for (int startIndex = 0, endIndex = 0; endIndex < length; ) {
if (charSet.contains(s.charAt(endIndex))) {
// 如果当前字符已经在HashSet中,就将HashSet中startIndex对应的字符移除,缩小窗口
charSet.remove(s.charAt(startIndex++));
} else {
//如果当前字串不存在HashSet中们就将他添加到HashSet集合中,在同时更新字串的长度
charSet.add(s.charAt(endIndex++));
sum = Math.max(sum, charSet.size());
}
}
//字串的长度
return sum;
}