💻 [LeetCode Hot100] 无重复字符的最长子串 ,滑动窗口+哈希表,Java实现!图解+代码,小白也能秒懂!
✏️本文对应题目链接:无重复字符的最长子串
📌 题目描述
给定一个字符串 s,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
输入:s = "abcabcbb"
输出:3
解释:因为无重复字符的最长子串是 "abc",所以其长度为 3。
🧠 解题思路(图文分解)
❗ 核心难点
如何高效找到不含重复字符的最长子串?
方法一:滑动窗口 + 哈希表(黄金思路)✨
关键步骤:
- 初始化:
- 使用哈希表记录字符最后一次出现的位置
- 定义滑动窗口的左右边界
left和right
- 遍历字符串:
- 如果当前字符已存在于哈希表,并且其位置在
left右侧,则更新left到重复字符的下一个位置 - 更新当前字符在哈希表中的位置
- 计算当前窗口长度,并更新最大值
- 如果当前字符已存在于哈希表,并且其位置在
- 返回结果:最长子串的长度
图解滑动窗口
输入字符串:
s = "abcabcbb"
步骤1:初始化
left = 0, right = 0
maxLen = 0
哈希表:{}
步骤2:遍历字符串
right=0: 字符'a' → 哈希表={'a':0} → 窗口长度=1 → maxLen=1
right=1: 字符'b' → 哈希表={'a':0, 'b':1} → 窗口长度=2 → maxLen=2
right=2: 字符'c' → 哈希表={'a':0, 'b':1, 'c':2} → 窗口长度=3 → maxLen=3
right=3: 字符'a' → 'a'已存在,且位置0 >= left → 更新left=1 → 哈希表={'a':3, 'b':1, 'c':2} → 窗口长度=3 → maxLen=3
right=4: 字符'b' → 'b'已存在,且位置1 >= left → 更新left=2 → 哈希表={'a':3, 'b':4, 'c':2} → 窗口长度=3 → maxLen=3
right=5: 字符'c' → 'c'已存在,且位置2 >= left → 更新left=3 → 哈希表={'a':3, 'b':4, 'c':5} → 窗口长度=3 → maxLen=3
right=6: 字符'b' → 'b'已存在,且位置4 >= left → 更新left=5 → 哈希表={'a':3, 'b':6, 'c':5} → 窗口长度=2 → maxLen=3
right=7: 字符'b' → 'b'已存在,且位置6 >= left → 更新left=7 → 哈希表={'a':3, 'b':7, 'c':5} → 窗口长度=1 → maxLen=3
最终结果:
maxLen = 3
🚀 代码实现
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
// 哈希表记录字符最后一次出现的位置
Map<Character, Integer> map = new HashMap<>();
int maxLen = 0; // 最长子串的长度
int left = 0; // 滑动窗口的左边界
// 遍历字符串
for (int right = 0; right < s.length(); right++) {
char currentChar = s.charAt(right);
// 如果字符已存在,并且位置在left右侧,则更新left
if (map.containsKey(currentChar) {
left = Math.max(left, map.get(currentChar) + 1);
}
// 更新字符的位置
map.put(currentChar, right);
// 计算当前窗口长度,并更新最大值
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
}
💡 复杂度分析
- 时间复杂度:O(n) → 只需遍历字符串一次
- 空间复杂度:O(min(m, n)) → 哈希表存储字符,
m为字符集大小
方法二:滑动窗口 + 数组(优化空间复杂度)
关键思路:用数组代替哈希表,适用于字符集较小的情况(如ASCII字符)。
class Solution {
public int lengthOfLongestSubstring(String s) {
int[] lastIndex = new int[128]; // ASCII字符集
Arrays.fill(lastIndex, -1); // 初始化数组
int maxLen = 0;
int left = 0;
for (int right = 0; right < s.length(); right++) {
char currentChar = s.charAt(right);
// 如果字符已存在,并且位置在left右侧,则更新left
if (lastIndex[currentChar] >= left) {
left = lastIndex[currentChar] + 1;
}
// 更新字符的位置
lastIndex[currentChar] = right;
// 计算当前窗口长度,并更新最大值
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
}
🌟 总结要点
✅ 滑动窗口核心思想:动态维护无重复字符的子串
✅ 哈希表/数组作用:快速定位字符的最后出现位置
✅ 适用场景:字符串匹配、子串问题
5866



被折叠的 条评论
为什么被折叠?



