一、题目
原题地址:3.无重复字符的最长子串
二、题解
方法: 双指针
1.思路及算法
-
这道题主要用到思路是:滑动窗口。什么是滑动窗口?
-
其实就是一个队列,比如例题中的
abcabcbb
,进入这个队列(窗口)为abc
满足题目要求,当再进入a
,队列变成了abca
,这时候不满足要求。所以,我们要移动这个队列! -
如何移动?我们只要把队列的左边的元素移出就行了,直到满足题目要求!一直维持这样的队列,找出队列出现最长的长度时候,求出解!
2.代码
/**
* @author : lightupworld
* @description: https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
* @date 2021/5/11 20:17
*/
public class LengthOfLongestSubstring {
public static int lengthOfLongestSubstring(String s) {
//异常处理
if (s == null || s.length() == 0) {
return 0;
}
/*
后面的逻辑可以包含这种情况
if (s.length() == 1) {
return 1 ;
}
*/
//定义返回结果 和 双指针的左边窗口变量
int maxLen = 0;
int left = 0;
//创建map 存储遍历结果
Map<Character, Integer> hashmap = new HashMap<>();
//遍历字符串
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (hashmap.containsKey(chars[i])) {
//如果出现重复的字符,就要开始滑动窗口,更新左边界
left = Math.max(hashmap.get(chars[i]) + 1, left);
//left = hashmap.get(chars[i]) + 1); 不能直接map去获取更新left, 如果相同的字符出现在靠后面,left可能出现倒退。一定要保持left增加
}
hashmap.put(chars[i], i);
maxLen = Math.max(maxLen, i - left + 1);
}
return maxLen;
}
//主函数用于测试
public static void main(String[] args) {
//String s = "pabcdhifgwwkew";
String s = "abba";
System.out.println(lengthOfLongestSubstring(s));
}
}
3.复杂度分析
-
时间复杂度:O(N),其中 N 是字符串的长度。左指针和右指针分别会遍历整个字符串一次。
-
空间复杂度:O(∣Σ∣),其中Σ 表示字符集(即字符串中可以出现的字符),|Σ∣ 表示字符集的大小。在本题中没有明确说明字符集,因此可以默认为所有 ASCII 码在 [0, 128) 内的字符,即 |Σ∣ = 128。我们需要用到哈希集合来存储出现过的字符,而字符最多有∣Σ∣ 个,因此空间复杂度为O(∣Σ∣)。
4.注意事项
- ①字符串的遍历
String str = "JavaString" for (int i = 0; i < str.length; i ++) { System.out.println(str.charAt(i)) }
- ②字符串与字符的转换
String str = "JavaString" //字符串转成 char数组 char[] char = str.toCharArray() //字符串返回指定索引处的 char 值。 str.charAt(i)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-by-leetc-2/
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/hua-dong-chuang-kou-by-powcai/