题目要求
原题目链接:3. 无重复字符的最长子串
题目要求如下:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例如下:
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
———————————————————————————————————————————
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
———————————————————————————————————————————
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
———————————————————————————————————————————
示例 4:
输入: s = “”
输出: 0
解法:滑动窗口
思路
从头依次对字符串s进行遍历,每一次遍历到的字符作为子串的起始字符,再寻找以当前字符为起始的无重复最长子串,一次遍历即可解决问题。
可以使用一个Set集合来维护每一次遍历存储的无重复最长子串来对普通的遍历进行优化。假设现有字符串abcda,那么第一次遍历最长的无重复最长字串就是abcd,相应第二次遍历的角色bcda,其中bcd部分是在第二次遍历是没有必要进行重复比较的,因此可以使用一个集合存储,每一次遍历时移除Set集合首位,余下的字符串也一定是无重复的,继续向原字符串后比较集合,空间换时间。
解题过程中一个指针总是指向新子串起始位置,另一个指针总是寻找并指向当前最长无重复子串的结尾位置,两个指针动态组成不定长的子串,故名滑动窗口,本质还是双指针的一种。
完整AC代码
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> set = new HashSet<Character>();
int max = 0;
int right = -1;
for(int i = 0; i < s.length(); i++){
if(i != 0)set.remove(s.charAt(i - 1));
while(right + 1 < s.length() && !set.contains(s.charAt(right + 1)))set.add(s.charAt(right++ + 1));
max = Math.max(max, set.size());
}
return max;
}
}
复杂度分析
时间复杂度:O(N),n字符串长度,实际上两个指针都需要对字符串进行一次遍历时间复杂度O(2N),故总时间复杂度O(N)。
空间复杂度:O(S),S表示字符串内可能包含的字符总个数。