一、题目描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:
输入: s = ""
输出: 0
二、思路分析:
这道题首先要明确的就是字串是连续的整个字符串中连着的字符组合,子序列是只要按照顺序不连着也可以,这两个要区分,很重要。
这道题要的是最长吴重复的最长子串,首先想到的是什么?没错,就是穷举,穷举出所有的子串,找到最大的就行了呗,实际上正确答案也是穷举的思路,可问题是怎么穷举效率更高那?这才是本题的重点!!!效率高无非就是从时间复杂度、空间复杂度来着手。
时间复杂度就是精妙的算法,空间复杂度是合适的数据结构
大家请记住上面的话,这对于你今后做题优化效率非常重要。
对于找到所有字串,可以这么来,从第一个元素开始向后遍历,到一个重复元素为止,这样就得到了以第一个元素为首的最长无重复子串了,以此类推,找出所有元素为首的最长无重复字串;这样找出了所有的无重复字串了,可是还有一个问题,就是怎么去判断是否有重复元素那,大家想想那种数据结构能最好的去重那?答案是 Set 集合,无序也不重复的集合。这个方法称为 “滑动窗口”。好了,思路分析的差不多了,下面上代码。
三、AC代码
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() < 1) {
return 0;
}
Set<Character> set = new HashSet<>();
// 无重复子串的右侧下标
int right = 0;
// 最长的长度
int ans = 0;
int n = s.length();
for (int i = 0; i < n; i ++) {
// i 就是左侧下标
if (i != 0) {
// 当不是第一个元素时,要把之前的元素删除掉
set.remove(s.charAt(i - 1));
}
while (right < n && !set.contains(s.charAt(right))) {
// 当不存在重复字符时加入集合中
set.add(s.charAt(right));
// 右侧下标前进
right ++;
}
// 遇见重复字符了,比较得到最长的子串长度
ans = Math.max(ans, right - i);
}
return ans;
}
}
四、总结
时间复杂度就是精妙的算法,空间复杂度是合适的数据结构