题目描述
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
-
输入:
s = "abcabcbb"
-
输出:
3
-
解释: 无重复字符的最长子串是
"abc"
,其长度为 3。 -
输入:
s = "bbbbb"
-
输出:
1
-
解释: 无重复字符的最长子串是
"b"
,其长度为 1。 -
输入:
s = "pwwkew"
-
输出:
3
-
解释: 无重复字符的最长子串是
"wke"
,其长度为 3。
解题思路
使用滑动窗口算法来解决这个问题。滑动窗口的基本思路是使用两个指针来标记一个窗口的开始和结束位置,然后不断调整这两个指针来找到符合条件的最长子串。
具体步骤如下:
-
初始化变量:
start
和end
两个指针分别表示当前窗口的起始和结束位置。maxLength
表示找到的最长无重复字符子串的长度。- 使用一个哈希表或数组
charIndex
来记录每个字符最后出现的位置。
-
滑动窗口操作:
- 遍历字符串中的每一个字符,使用
end
指针逐个扫描。 - 如果当前字符已经在
charIndex
中并且它的索引值大于等于start
,这意味着出现了重复字符,此时需要更新start
位置为当前字符上次出现位置的下一个位置。 - 无论是否出现重复字符,都要更新当前字符在
charIndex
中的索引值,并计算当前无重复子串的长度,然后更新maxLength
。
- 遍历字符串中的每一个字符,使用
-
返回结果:
- 最终返回
maxLength
,即为最长无重复子串的长度。
- 最终返回
代码实现
C 实现
#include <stdio.h>
#include <string.h>
int lengthOfLongestSubstring(char * s) {
int charIndex[128] = {0}; // ASCII 字符集大小
int maxLength = 0;
int start = 0;
for (int end = 0; s[end] != '\\0'; end++) {
if (charIndex[s[end]] > start) {
start = charIndex[s[end]];
}
charIndex[s[end]] = end + 1; // 更新字符的最新索引
int currentLength = end - start + 1;
if (currentLength > maxLength) {
maxLength = currentLength;
}
}
return maxLength;
}
int main() {
char s[] = "abcabcbb";
printf("Longest substring length: %d\\n", lengthOfLongestSubstring(s));
return 0;
}
Java 实现
import java.util.HashMap;
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> charIndex = new HashMap<>();
int maxLength = 0;
int start = 0;
for (int end = 0; end < s.length(); end++) {
char currentChar = s.charAt(end);
if (charIndex.containsKey(currentChar)) {
start = Math.max(start, charIndex.get(currentChar) + 1);
}
charIndex.put(currentChar, end);
maxLength = Math.max(maxLength, end - start + 1);
}
return maxLength;
}
public static void main(String[] args) {
Solution solution = new Solution();
String s = "abcabcbb";
System.out.println("Longest substring length: " + solution.lengthOfLongestSubstring(s));
}
}
Python 实现
def length_of_longest_substring(s: str) -> int:
char_index = {}
max_length = 0
start = 0
for end in range(len(s)):
if s[end] in char_index:
start = max(start, char_index[s[end]] + 1)
char_index[s[end]] = end
max_length = max(max_length, end - start + 1)
return max_length
# 测试
s = "abcabcbb"
print("Longest substring length:", length_of_longest_substring(s))
时间复杂度
该算法的时间复杂度为 On,其中 n
是字符串的长度。因为每个字符在最坏情况下被遍历两次,一次由 end
指针,一次由 start
指针。