- 操作系统:ubuntu22.04
- IDE:Visual Studio Code
- 编程语言:C++11
题目描述
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
假设字符串中的所有字符都是英文小写字母,即 a 到 z。
示例:
输入: "abcabcbb"
输出: 3
解释: 最长不含重复字符的子字符串是 "abc",其长度为 3。
输入: "bbbbb"
输出: 1
解释: 最长不含重复字符的子字符串是 "b",其长度为 1。
解法思路:滑动窗口 + 哈希表
这是一道经典的滑动窗口问题,利用双指针和哈希表(或数组)来高效求解。
核心思想:
- 使用两个指针 left 和 right 维护一个窗口;
- 使用哈希表记录每个字符最近出现的位置;
- 当遇到重复字符时,移动左指针至重复字符上次出现位置的右边一位;
- 计算当前窗口大小并更新最大值。
代码示例
#include <string>
#include <unordered_map>
using namespace std;
class Solution {
public:
int lengthOfLongestSubstring( string s )
{
unordered_map< char, int > charIndexMap; // 记录字符最近出现的位置
int maxLength = 0;
int left = 0; // 窗口左边界
int maxStart = 0; // 最长子串的起始位置
for ( int right = 0; right < s.size(); ++right )
{
if ( charIndexMap.find( s[ right ] ) != charIndexMap.end() )
{
// 如果当前字符已经在窗口中出现过,移动左指针
left = max( left, charIndexMap[ s[ right ] ] + 1 );
}
// 更新当前字符的位置
charIndexMap[ s[ right ] ] = right;
// 更新最大长度
maxLength = max( maxLength, right - left + 1 );
// 判断是否更新最大长度
int currentLength = right - left + 1;
if (currentLength > maxLength) {
maxLength = currentLength;
maxStart = left;
}
}
std::cout<<s.substr(maxStart, maxLength)<<" " ;
return maxLength;
}
};
#include <iostream>
int main()
{
Solution sol;
cout << sol.lengthOfLongestSubstring( "abcabcbb" ) << endl; // 输出 3
cout << sol.lengthOfLongestSubstring( "bbbbb" ) << endl; // 输出 1
cout << sol.lengthOfLongestSubstring( "pwwkew" ) << endl; // 输出 3
return 0;
}
运行结果
abc 3
b 1
pww 3