「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
题目描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
思路分析
先是用最简单的穷举法,两次for循环算出最大长度。比较坑的点是需要注意字符串里面包含数字已经空字符。
int lengthOfLongestSubstring(string s) {
if(s == ""){
return 0;
}
if(s.size() == 1)return 1;
map<char, int> mp;
int ret = 0, tmp = 0;
// for(int i = 0; i < 26; i++)arr[i] = 0;
for(int i = 0; i < s.size(); i++){
// if(s[i] == ' ')continue;
tmp = 0;
for(int j = i; j < s.size(); j++){
mp[s[j]] ++;
if(mp[s[j]] == 2){
break;
}
tmp ++;
}
ret = max(ret, tmp);
mp.clear();
}
return max(ret, tmp);
}
接下来就是优化的事情了,题中说明一个最长子串而不是子序列,意味着一个子串必有pq,因此本题可以理解为找到距离最远的pq位置,须知假设p点为i,q点为j,构成p点为i的前提下的最长子串,当p = i+1时,如果会出现最长子串,一定是让q点在j+1以后,如果不能实现,则意味此处并不满足最长子串。
其实这也是通常滑动窗口的思想,我们通过滑动窗口将O(n^2)的时间复杂度变成了O(n)(当然就这道题而言,时间复杂度是p和q移动的次数,也就是小于2n)。
具体实现
以下是关键代码。
for(int i = 0; i < s.size(); i++){
while(j < s.size() && mp[s[j]] == 0){
mp[s[j]] = 1;
j++;
}
// cout << i << " " << j << endl;
ret = max(j - i, ret);
if(j == s.size())break;
mp[s[i]] = 0;
}