代码训练(41)无重复字符的最长子串
Author: Once Day Date: 2025年6月28日
漫漫长路,才刚刚开始…
全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客
参考文章:
1. 原题
给定一个字符串
s
,请你找出其中不含有重复字符的 最长 子串 的长度。提示:
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
2. 分析
这个题目要求我们找出给定字符串中最长的不含重复字符的子串,并返回这个子串的长度。字符串可能由英文字母、数字、符号和空格组成。
为了解决这个问题,我们可以使用滑动窗口的方法。滑动窗口是一种可以将嵌套的循环问题转换为单循环问题,从而降低时间复杂度的技术。具体到这个问题,我们可以定义两个指针,一个指向子串的开始位置,另一个随着遍历逐步向后移动,从而形成一个窗口。我们还需要一个数据结构来存储窗口内的字符,以快速判断字符是否重复,通常使用哈希表实现。
分析步骤:
- 初始化两个指针 left 和 right,分别代表子串的起始和结束位置,初始化哈希表用于存储字符及其在字符串中的位置。
- 遍历字符串,对于每个字符:
- 如果字符已经在哈希表中且其索引不小于 left,说明窗口内有重复字符,需要移动 left 指针到重复字符的下一个位置。
- 更新哈希表中当前字符的位置。
- 更新最大子串长度。
- 返回记录的最大长度。
举例分析:例如,对于字符串 “abcabcbb”:
- 初始化 left=0, right=0, 最大长度 max_len=0。
- right=0,字符 ‘a’,哈希表更新为 {‘a’: 0},max_len 更新为 1。
- right=1,字符 ‘b’,哈希表更新为 {‘a’: 0, ‘b’: 1},max_len 更新为 2。
- right=2,字符 ‘c’,哈希表更新为 {‘a’: 0, ‘b’: 1, ‘c’: 2},max_len 更新为 3。
- right=3,字符 ‘a’ 重复,left 更新为 1,哈希表更新为 {‘a’: 3, ‘b’: 1, ‘c’: 2}。
- 依此类推,直到遍历完整个字符串。
性能优化关键点:
- 使用哈希表来快速查找和更新字符的位置。
- 只需遍历一次字符串,时间复杂度为 O(n)。
- 空间复杂度主要由哈希表引起,最坏情况下为 O(min(m, n)),其中 m 是字符集的大小。
3. 代码实现
#include <stdio.h>
#include <string.h>
#define MAX_CHARS 256
int lengthOfLongestSubstring(char * s) {
int n = strlen(s);
int longest = 0;
int left = 0;
int charIndex[MAX_CHARS]; // 存储每个字符的最新位置
memset(charIndex, -1, sizeof(charIndex));
for (int right = 0; right < n; right++) {
if (charIndex[s[right]] >= left) {
left = charIndex[s[right]] + 1;
}
charIndex[s[right]] = right;
longest = longest > right - left + 1 ? longest : right - left + 1;
}
return longest;
}
int main() {
char s[] = "abcabcbb";
printf("The length of the longest substring without repeating characters is: %d\n", lengthOfLongestSubstring(s));
return 0;
}
4. 总结
这个问题考察了对滑动窗口技术的理解和应用,以及对数据结构(如哈希表)的使用来优化查找和更新操作。通过这类问题,可以提升对字符串处理和算法优化的能力。要进一步提高,可以练习更多涉及滑动窗口和字符串处理的问题,同时也要注意边界条件和特殊输入的处理。