无重复字符的最长子串(七)

一、题目描述

这是 LeetCode 热题 HOT 100 上第三题:无重复字符的最长子串,难度为 中等

Tag:「哈希表」、「数组」、「滑动窗口」

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

1
2
3
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3

示例 2:

1
2
3
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1

示例 3:

1
2
3
4
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3
  请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

1、0 <= s.length <= 5 * 104

2、s 由英文字母、数字、符号和空格组成

二、解题思路

暴力解法时间复杂度较高,会达到 O(n^2),故而采取滑动窗口的方法降低时间复杂度

什么是滑动窗口?

其实就是一个队列,比如下图中的 dvdf,进入这个队列(窗口)为 dv 满足题目要求,当再进入 d,队列变成了 dvd,这时候不满足要求。所以,我们要移动这个队列!

如何移动?

我们只要把队列的左边的元素移出就行了,直到满足题目要求!

一直维持这样的队列,找出队列出现最长的长度时候,求出解!

image-20221210215201969.png

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
//定义一个 map 存储,其中 key 值为字符,value 值为字符位置 +1,加 1 表示从字符位置后一个才开 //始不重复
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int right = 0; right < s.length(); right++){
//如果存在相同的 key ,则 left 往右移动
if(map.containsKey(s.charAt(right))){
left = Math.max(left,map.get(s.charAt(right)) + 1);
}
map.put(s.charAt(right),right);
//每次比较并获取最大无重复字符子串
max = Math.max(max,right-left+1);
}
return max;

}
}

时间复杂度和空间复杂度分析:

时间复杂度:O(n),其中 n 是字符串的长度。左指针和右指针分别会遍历整个字符串一次

空间复杂度:O(|Σ|),其中 Σ 表示字符集(即字符串中可以出现的字符),|Σ| 表示字符集的大小。在本题中没有明确说明字符集,因此可以默认为所有 ASCII 码在 [0, 128) 内的字符,即 |Σ| = 128。我们需要用到哈希集合来存储出现过的字符,而字符最多有 |Σ| 个,因此空间复杂度为 O(|Σ|)。

三、总结

本道算法题难度中等,主要考察了我们对滑动窗口的掌握,定义好左右指针,结合 map 在合适的时候移动指针,并能轻松的解决该题

好了,本篇文章到这里就结束了,感谢你的阅读🤝


无重复字符的最长子串(七)
https://sweetying520.github.io/2022/08/09/A7-无重复字符的最长子串(七)/
作者
sweetying
发布于
2022年8月9日
许可协议