一、题目:
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
假设字符串中只包含从 a
到 z
的字符。
数据范围
输入字符串长度 [0,1000][0,1000]。
样例
输入:"abcabc"输出:3
二、代码展示
#include <stdio.h>
#include <string.h>int lengthOfLongestSubstring(char* s) {int n = strlen(s);int maxLength = 0;int start = 0;int charIndex[26]; // 记录每个字符最后出现的位置// 初始化charIndex数组,将所有字符的最后出现位置设置为-1for (int i = 0; i < 26; i++) {charIndex[i] = -1;}for (int end = 0; end < n; end++) {// 如果字符已经出现过,并且出现位置在当前窗口内,更新窗口的起始位置if (charIndex[s[end] - 'a'] >= start) {start = charIndex[s[end] - 'a'] + 1;}// 更新字符的最后出现位置charIndex[s[end] - 'a'] = end;// 更新最大长度if (end - start + 1 > maxLength) {maxLength = end - start + 1;}}return maxLength;
}int main() {char input[] = "abcabc";int result = lengthOfLongestSubstring(input);printf("输出:%d\n", result);return 0;
}
这个程序中,我们使用了一个长度为26的数组charIndex
来记录每个字符最后一次出现的位置。我们使用两个指针start
和end
来构建滑动窗口,其中start
表示窗口的起始位置,end
表示窗口的结束位置。在遍历字符串的过程中,我们不断调整窗口的位置,并更新最大长度。
三、解析
for (int end = 0; end < n; end++) {// 如果字符已经出现过,并且出现位置在当前窗口内,更新窗口的起始位置if (charIndex[s[end] - 'a'] >= start) {start = charIndex[s[end] - 'a'] + 1;}// 更新字符的最后出现位置charIndex[s[end] - 'a'] = end;// 更新最大长度if (end - start + 1 > maxLength) {maxLength = end - start + 1;}}
上面这段代码是解决最长不含重复字符子字符串的核心逻辑。
-
for (int end = 0; end < n; end++)
: 这是一个循环,遍历整个字符串。end
代表当前窗口的结束位置,从字符串的开头逐步移动到结尾。 -
if (charIndex[s[end] - 'a'] >= start)
: 这个条件判断检查当前字符s[end]
是否已经在当前窗口中出现过。charIndex[s[end] - 'a']
表示字符s[end]
上次出现的位置。如果上次出现的位置在当前窗口内(即大于等于start
),就说明这个字符重复了。 -
start = charIndex[s[end] - 'a'] + 1;
: 如果发现重复字符,就更新窗口的起始位置为上次出现位置的下一个位置,以确保不包含重复字符。 -
charIndex[s[end] - 'a'] = end;
: 更新字符s[end]
的最后一次出现位置为当前位置end
。 -
if (end - start + 1 > maxLength)
: 在每次迭代中,都比较当前窗口的长度(end - start + 1
)是否大于已知的最大长度maxLength
,如果是,则更新maxLength
。
整个过程就是通过滑动窗口的方式不断调整窗口的起始和结束位置,确保窗口内的字符都是不重复的,同时不断更新最大长度。最终,maxLength
就是最长不含重复字符的子字符串的长度。