1.题目描述
输入一个字符串,给出该字符串的最长无重复字符的子串。
2.分析
解题思路1:
暴力解题:遍历所有子串,判断是否无重复子串,把最长的记录下来。
解题思路2:
滑动窗口法:所谓滑动窗口是一个形象的说法。这里指的是使用两个指针left和right表示子串的两端。用一个结构来记录每个字符在窗口中出现的次数。先走右指针right,把右指针指向的字符放入map中,记录此字符出现的次数,然后右指针往前走一位。接着收缩左指针,当当前字符对应的value大于1时,表明该字符在窗口中,收缩左窗口,使得不符合要求的字符划出窗口内。
若笔者笔力有限,叙述的不够清晰,建议对照下面的代码来理解。
3.代码
#include<iostream>
#include<vector>
#include<unordered_map>
#include<string>
using namespace std;
//返回一个字符串的最长子串,这个子串满足每个字符都不重复
//即最长无重复字串
string LengthestSubstring(string s) {
//滑动窗口法
if (s.size() < 2)
return s;
int left=0, right = 0;//设置两个指针,指示窗口的两端
int max_left=0, max_right = 0;
unordered_map<char, int> windows;//key,value 用来表示某字符在窗口中出现的次数
while (right < s.size())
{
char c = s[right];
windows[c]++;
right++;
while (windows[c] > 1)
{
char c2 = s[left];
left++;
windows[c2]--;
}
//每次滑动窗口后,更新字串
if (right - left > max_right - max_left) {
max_left = left;
max_right = right;
}
}
return s.substr(max_left, max_right - max_left);//substr函数有两个参数,开始位置和长度
}
int main()
{
string str = "abcdeabcdefgdeabc";
cout << LengthestSubstring(str) << endl;
return 0;
}