C语言实战:滑动窗口算法解决字符串最长无重复子串问题(附完整代码)

张开发
2026/4/16 7:03:06 15 分钟阅读

分享文章

C语言实战:滑动窗口算法解决字符串最长无重复子串问题(附完整代码)
C语言实战滑动窗口算法解决字符串最长无重复子串问题附完整代码滑动窗口算法是解决字符串和数组问题的利器尤其适合处理子串或子数组相关的问题。今天我们就来深入探讨如何用C语言实现滑动窗口算法解决最长无重复子串这一经典问题。1. 滑动窗口算法基础滑动窗口算法通过维护一个可动态调整的窗口来高效解决问题。这个窗口通常由两个指针左指针和右指针定义可以在数组或字符串上滑动。核心思想右指针负责扩展窗口探索新元素左指针负责收缩窗口维持窗口内元素的合法性在移动过程中记录所需的最优解对于字符串问题滑动窗口算法的时间复杂度通常为O(n)远优于暴力解法的O(n²)。提示理解滑动窗口的关键在于明确窗口何时扩展、何时收缩以及如何更新最优解。2. 最长无重复子串问题解析给定一个字符串找出其中不含有重复字符的最长子串的长度。例如输入abcabcbb输出3abc输入bbbbb输出1b输入pwwkew输出3wke解决思路使用哈希表记录字符最后一次出现的位置维护左右指针定义当前窗口当遇到重复字符时调整左指针位置在每一步更新最大长度#include stdio.h #include string.h #define MAX_CHAR 256 int lengthOfLongestSubstring(char *s) { int lastIndex[MAX_CHAR] {0}; // 记录字符最后出现的位置 int maxLen 0; int start 0; // 窗口起始位置 for (int end 0; s[end] ! \0; end) { char current s[end]; if (lastIndex[current] start) { start lastIndex[current]; } lastIndex[current] end 1; // 更新字符位置 int currentLen end - start 1; if (currentLen maxLen) { maxLen currentLen; } } return maxLen; }3. 代码逐行解析与优化让我们深入分析上述代码的关键部分哈希表初始化int lastIndex[MAX_CHAR] {0};这里使用大小为256的数组模拟哈希表覆盖所有ASCII字符。数组初始化为0表示字符尚未出现。窗口调整逻辑if (lastIndex[current] start) { start lastIndex[current]; }当发现当前字符之前出现过在窗口内就将窗口起点移动到该字符上次出现位置的下一位。长度计算与更新int currentLen end - start 1; if (currentLen maxLen) { maxLen currentLen; }每次迭代都计算当前窗口长度并更新最大值。优化建议添加输入验证if (s NULL || *s \0) return 0;使用更明确的变量名增强可读性添加注释说明关键算法步骤4. 常见错误与调试技巧初学者在实现滑动窗口算法时常遇到以下问题问题1窗口收缩条件错误症状返回的长度总是偏大原因没有正确处理重复字符的位置修复确保lastIndex存储的是字符的下一个位置问题2哈希表初始化不当症状随机结果或段错误原因未初始化哈希表或大小不足修复使用{0}初始化确保大小覆盖所有字符问题3边界条件处理不当空字符串全相同字符的字符串单字符字符串调试技巧打印窗口变化过程printf(Window [%d,%d]: , start, end); for (int i start; i end; i) { printf(%c, s[i]); } printf(\n);跟踪哈希表状态使用简单测试用例逐步验证5. 算法扩展与应用掌握了基本解法后我们可以考虑以下扩展变种1输出最长子串本身void longestUniqueSubstring(char *s, char *result) { int lastIndex[MAX_CHAR] {0}; int maxLen 0, start 0, resultStart 0; for (int end 0; s[end] ! \0; end) { char current s[end]; if (lastIndex[current] start) { start lastIndex[current]; } lastIndex[current] end 1; int currentLen end - start 1; if (currentLen maxLen) { maxLen currentLen; resultStart start; } } strncpy(result, s resultStart, maxLen); result[maxLen] \0; }变种2允许最多k个重复字符只需修改窗口收缩条件当窗口内某字符出现超过k次时才收缩。性能对比方法时间复杂度空间复杂度适用场景暴力法O(n²)O(1)小规模数据滑动窗口O(n)O(m)通用方案优化滑动窗口O(n)O(1)字符集固定6. 实战练习与提高为了真正掌握滑动窗口算法建议尝试以下练习最小覆盖子串给定字符串S和T在S中找到包含T所有字符的最短子串长度最小的子数组给定数组和正整数s找出和≥s的长度最小的连续子数组最多包含两个不同字符的最长子串替换后的最长重复字符给定字符串和整数k替换k个字符后找到最长重复字符子串练习提示先明确窗口的合法条件确定窗口扩展和收缩的时机考虑如何高效记录窗口状态处理边界条件和特殊输入// 练习示例长度最小的子数组 int minSubArrayLen(int target, int* nums, int numsSize) { int minLen INT_MAX; int sum 0; int left 0; for (int right 0; right numsSize; right) { sum nums[right]; while (sum target) { int currentLen right - left 1; if (currentLen minLen) { minLen currentLen; } sum - nums[left]; } } return minLen INT_MAX ? 0 : minLen; }在实际项目中应用滑动窗口算法时记得考虑代码的可读性和可维护性。添加适当的注释拆分复杂逻辑为函数并进行充分的测试。

更多文章