题目
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成
解题思路:用滑动窗口来记录无重复字符串,用什么数据结构?怎么表示窗口的左边界和右边界
①用Set来记录无重复字符串,定义左右指定指向边界,长度=右边界-左边界
时间复杂度:O(N) 空间复杂度O(),表示最多可能出现的字符,最大为128,也就是O(1)的空间复杂度
class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
if(n<=1){
return n;
}
// 整体思路:l指向窗口左边界,r指向窗口右边界的下一个元素
int l = 0, r = 1;
HashSet<Character> set = new HashSet<>();
set.add(s.charAt(l));
int res = 0;
while(r<n){
// 没有重复,添加到窗口中,右边界右移
while(r<n && !set.contains(s.charAt(r))){
set.add(s.charAt(r));
r++;
}
// 出现重复,先比较当前窗口大小和res,再移除前面重复的元素,窗口左边界右移
res = Math.max(res, r-l);
set.remove(s.charAt(l));
l++;
}
return res;
}
}
②用Map来记录无重复字符串,key为字符,value为字符在数组中的下标,遍历字符串,定义左指针记录左边界,i为右边界
时间复杂度:O(N),空间复杂度O(N)
class Solution {
public int lengthOfLongestSubstring(String s) {
int len = s.length();
int left = 0;
int maxLen = 0;
HashMap<Character,Integer> map = new HashMap<>();
for(int i = 0;i<len;i++){
// 出现重复字符串,判断是否要更新左边界
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i))+1);
}
map.put(s.charAt(i),i);
maxLen = Math.max(maxLen,i-left+1);
}
return maxLen;
}
}
③用Queue来记录无重复字符串,队列中只包含不重复的字符串
时间复杂度:在最坏情况下,每个字符最多被操作两次(一次入队,一次出队),因此整个算法的时间复杂度为 O(n)
空间复杂度:O(N)
class Solution {
public int lengthOfLongestSubstring(String s) {
//思路1:滑动指针的思想,用队列来存放不重复的子串,遇到重复的字符,就移出该字符及前面的字符
Queue<Character> queue = new LinkedList<>();
int length = 0;
if(s==null||"".equals(s)){return 0;}
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(queue.contains(c)){
//将c及之前的都移除掉
while(queue.peek()!=c){
queue.poll();
}
queue.poll();//把c弹出去
queue.offer(c);//这个地方一定要记得把当前字符移进来
}else{
queue.offer(c);
}
length = Math.max(length,queue.size());
}
return length;
}
}
④在评论区看到的解法
时间复杂度:外层循环O(N),内层循环,因为是不重复的字符所以不会超过128,时间复杂度是O(N*)
空间复杂度O(1)
public int lengthOfLongestSubstring(String s) {
int left = 0, length = 0, max = 0;
for(int right=0; right < s.length(); right++){
for(int k = left; k < right; k++){
if(s.charAt(k) == s.charAt(right)){
left = k+1;
length = right-left;
break;
}
}
length++;
max = Math.max(max,length);
}
return max;
}