给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度
示例 1:
输入:
s = "abcabcbb"
输出:
3
解释: 因为无重复字符的最长子串是 "abc"
,所以其长度为 3。
示例 2:
输入:
s = "bbbbb"
输出:
1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入:
s = "pwwkew"
输出:
3
解释: 因为无重复字符的最长子串是 "wke"
,所以其长度为 3。
请注意,你的答案必须是
子串 的长度,"pwke" 是一个子序列,
不是子串。
解题思路:
-
初始化变量:使用一个哈希表(或数组)来记录每个字符最近出现的位置。定义两个指针,
left
和right
,分别表示当前窗口的左右边界。初始时,left
和right
都指向字符串的开始。 -
滑动窗口:移动
right
指针,扩展窗口的右边界。对于每一个新字符,检查它是否已经在当前窗口中出现过(即其最近出现位置是否在left
的右侧)。 -
调整左边界:如果字符已经在窗口中存在,则将
left
指针移动到该字符上次出现位置的下一个位置,以确保窗口内没有重复字符。 -
更新最大长度:在每次移动
right
指针后,计算当前窗口的长度(right - left + 1
),并更新最大长度记录。
// 函数:计算字符串中不含重复字符的最长子串的长度
int lengthOfLongestSubstring(char * s) {int n = strlen(s); // 获取字符串的长度if (n == 0) return 0; // 如果字符串为空,直接返回0int lastIndex[256]; // 创建一个数组,用于记录每个字符最后出现的位置,ASCII字符共有256个memset(lastIndex, -1, sizeof(lastIndex)); // 初始化数组,将所有位置设为-1,表示字符未出现过int maxLen = 0; // 用于记录最长子串的长度int left = 0; // 滑动窗口的左边界for (int right = 0; right < n; right++) { // 遍历字符串,right是滑动窗口的右边界char currentChar = s[right]; // 当前字符if (lastIndex[currentChar] >= left) { // 如果当前字符在窗口内已经出现过left = lastIndex[currentChar] + 1; // 移动左边界到该字符上次出现位置的下一位}lastIndex[currentChar] = right; // 更新当前字符的最后出现位置int currentLen = right - left + 1; // 计算当前窗口的长度if (currentLen > maxLen) { // 如果当前窗口长度大于已知的最大长度maxLen = currentLen; // 更新最大长度}}return maxLen; // 返回最长子串的长度
}
实验小结:
本次实验通过实现滑动窗口算法,解决了寻找字符串中不含重复字符的最长子串长度的问题。实验过程中,首先明确了滑动窗口的基本思想,即通过动态调整窗口的左右边界来确保窗口内字符的唯一性。具体实现时,利用哈希表记录字符的最后出现位置,从而高效地判断重复字符并调整窗口边界。通过测试用例验证,算法能够正确处理不同场景,如连续重复字符、无重复字符等情况,确保了结果的准确性和高效性。实验加深了对滑动窗口技术的理解,并掌握了如何利用哈希表优化字符串处理问题。最终,算法的时间复杂度为O(n),空间复杂度为O(1)(固定大小的字符集),满足高效处理的要求。