小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
题目描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:
输入: s = "" 输出: 0
解题方式
方法1:暴力循环
用Set
结构判断字符是否重复,使用双重循环找出所有的不重复子串
代码
public int lengthOfLongestSubstring2(String s) {
if (s.equals("")){
return 0;
}
int max = 0;
// Set的作用是存储不重复的字串
// 使用Set存储字符串的每个字符,如果能存进去说明该字符没有重复
Set<Character> set = new HashSet<>();
int length = s.length();
// 双重循环,找出每个不重复的子串
for (int i = 0; i < length; i++) {
for (int j = i; j < length; j++){
boolean add = set.add(s.charAt(j));
// 没有存入set说明该字符已经在set中了
if (!add){
max = Math.max(max, set.size());
set.clear();
break;
}
// 处理最后一个字符未重复的情况
if (i == length - 1){
max = Math.max(max, set.size());
}
}
}
return max;
}
LeetCode运行结果
方法2: 滑动窗口
窗口包含的子符为不重复子串,计算每个窗口包含的长度并和当前记录的最大长度比较,如果当前子串长度大于记录的最大长度,则将当前子串长度记录成最大长度。
遍历字符串时,当前窗口长度 = 当前位置 - 上一个重复字符的位置 + 1
public static int lengthOfLongestSubstring1(String s) {
// 数组的位置表示字符,字符的对应位置存入该字符最后一次出现的下标
int[] last = new int[128];
Arrays.fill(last, -1);
int res = 0;
// 窗口开始位置
int start = 0;
// i表示窗口的结束位置
for (int i = 0; i < s.length(); i++) {
int ch = s.charAt(i);
// 窗口开始位置等于字符最后出现的后一位
// 该字符最后一次出现的位置为新的窗口开始位置
start = Math.max(start, last[ch] + 1);
// 如果当前窗口的长度大于已经记录的最大长度,则把当前窗口的长度记录为最大长度
res = Math.max(res, i - start + 1);
// 记录该字符最后一次出现的下标
last[ch] = i;
}
return res;
}
此解法来源于LeetCode
LeetCode运行结果