这道题目来自LeetCode热题100中的第3题,属于字符串处理类问题的经典题型。给定一个字符串s,要求找出其中不含有重复字符的最长子串的长度。比如输入"abcabcbb",最长无重复子串是"abc",长度为3。
在实际开发中,类似的需求经常出现在文本处理、数据清洗、生物信息学等领域。比如检测用户输入中是否存在重复字符、分析DNA序列中的独特片段、或者验证密码强度时检查连续不重复字符的长度等。掌握这类问题的解法,对提升编程思维和解决实际问题都很有帮助。
最直接的思路是检查所有可能的子串,判断是否有重复字符。具体步骤:
这种方法时间复杂度为O(n³),在LeetCode上提交会超时。主要问题在于:
更高效的解法是使用滑动窗口(Sliding Window)技术。维护一个窗口[i, j),表示当前考察的子串。关键观察:
这样每个字符最多被访问两次(i和j各一次),时间复杂度降为O(n)。空间复杂度O(min(m, n)),其中m是字符集大小。
python复制def lengthOfLongestSubstring(s: str) -> int:
char_set = set()
max_len = 0
i = 0
for j in range(len(s)):
while s[j] in char_set:
char_set.remove(s[i])
i += 1
char_set.add(s[j])
max_len = max(max_len, j - i + 1)
return max_len
代码要点:
char_set记录当前窗口中的字符注意:这里内层是while循环而不是if,因为可能连续多个字符都需要被移除。例如"abba"的情况,当j=3时,需要先移除a再移除b。
可以用哈希表记录字符的最新索引,直接跳转左边界:
python复制def lengthOfLongestSubstring(s: str) -> int:
last_index = {}
max_len = 0
i = 0
for j in range(len(s)):
if s[j] in last_index:
i = max(i, last_index[s[j]] + 1)
last_index[s[j]] = j
max_len = max(max_len, j - i + 1)
return max_len
优势:
| 输入 | 输出 | 说明 |
|---|---|---|
| "abcabcbb" | 3 | 标准案例 |
| "bbbbb" | 1 | 全部重复 |
| "pwwkew" | 3 | 最长在中间 |
| "" | 0 | 空字符串 |
| " " | 1 | 单个空格 |
| "abba" | 2 | 左边界回退 |
算法天然支持各种字符:
两种优化实现都是O(n):
取决于字符集大小:
python复制last_index = [-1] * 128 # ASCII码范围
python复制print(f"i={i}, j={j}, window={s[i:j+1]}")
java复制public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
int max = 0;
for (int i = 0, j = 0; j < s.length(); j++) {
if (map.containsKey(s.charAt(j))) {
i = Math.max(i, map.get(s.charAt(j)) + 1);
}
map.put(s.charAt(j), j);
max = Math.max(max, j - i + 1);
}
return max;
}
注意:Java的HashMap比Python的dict稍慢,可以考虑用int[128]优化。
cpp复制int lengthOfLongestSubstring(string s) {
unordered_map<char, int> lastIndex;
int maxLen = 0, i = 0;
for (int j = 0; j < s.size(); j++) {
if (lastIndex.find(s[j]) != lastIndex.end()) {
i = max(i, lastIndex[s[j]] + 1);
}
lastIndex[s[j]] = j;
maxLen = max(maxLen, j - i + 1);
}
return maxLen;
}
C++版本通常运行最快,unordered_map效率很高。
类似思想可用于:
在实际工程中遇到类似问题时,可以回想这个经典解法,往往能找到优化思路。比如处理日志流时寻找特定模式,或者监控系统中检测异常序列等。