1 3. 无重复字符的最长子串
一开始的思路:同向双指针 + unordered_set,但是 TLE 了。原因竟然是多余的 cout 占时间,第一次见,去掉 cout 就ac了。
AC代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// 同向双指针 + unordered_set
int l = 0;
int r = 0;
unordered_map<char,int> tmp;
int tmp1 = 0;
int ans = 0;
while(r < s.size())
{
if(tmp.find(s[r]) != tmp.end()) //找到了
{
l = tmp[s[r]] + 1;
r = l;
tmp1 = 0;
tmp.clear();
}
else
{
tmp.insert({s[r],r});
tmp1++;
ans = max(ans,tmp1);
r++;
// cout << r << endl; // 不能cout! 输出时间也占很多
}
}
return ans;
}
};
学习一个思路——滑动窗口,其实双指针也可以写成和滑动窗口一样作用的形式。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// 滑动窗口的写法
unordered_set<int> x;
int ans = 0;
int tmp = 0;
int l = 0;
for(int i = 0; i < s.size();i++)
{
while(x.find(s[i]) != x.end())
{
x.erase(s[l++]);
tmp--;
}
x.insert(s[i]);
tmp++;
ans = max(ans,tmp);
}
return ans;
}
};
2 438. 找到字符串中所有字母异位词
坑:multiset 用erase时候会把元素相同的全部删掉,如果只想删掉一个的话需要:
// tmp.erase(s[l]); // 有多个重复的会全部删掉 auto it = tmp.find(s[l]); tmp.erase(it);
一开始思路:滑动窗口+用multiset,但是TLE了。
TLE代码:
class Solution {
public:
vector<int> findAnagrams(string s, string p)
{
// 滑动窗口+用multiset
vector<int> ans;
multiset<int> pp;
for(int i = 0; i < p.size();i++)
pp.insert(p[i]);
multiset<int> tmp;
int l = 0;
for(int i = 0; i < s.size();i++)
{
tmp.insert(s[i]);
if(tmp.size() == pp.size())
{
if(tmp == pp)
ans.push_back(l);
// tmp.erase(s[l]); // 有多个重复的会全部删掉
auto it = tmp.find(s[l]);
tmp.erase(it);
l++;
}
}
return ans;
}
};
后来改成unordered_map 就行了,但是有两个地方需要注意:判断两个unordered_map 的代表的second和是否相等,以及各个first对应的second是否相同,需要单独写个函数,不能直接 unordered_map a == unordered_map b!
AC代码:
class Solution {
public:
bool geshusame(unordered_map<char,int> a,int n)
{
int num = 0;
for(auto it = a.begin(); it != a.end(); it++)
num += it->second;
if(num == n)return 1;
else return 0;
}
bool same(unordered_map<char,int> a,unordered_map<char,int> b)
{
for(auto it = b.begin(); it != b.end();it++)
if(a[it->first] != it->second)return 0;
return 1;
}
vector<int> findAnagrams(string s, string p)
{
// 滑动窗口+用unordered_map
vector<int> ans;
unordered_map<char,int> pp;
for(int i = 0; i < p.size();i++)
pp[p[i]]++;
unordered_map<char,int> tmp;
int l = 0;
for(int i = 0; i < s.size();i++)
{
tmp[s[i]]++;
if(geshusame(tmp,p.size()))
{
if(same(tmp,pp))
ans.push_back(l);
tmp[s[l]]--;
l++;
}
}
return ans;
}
};
总结:
用时:3h20min。
1. 滑动窗口算双指针中的一种,一般结合unordered_set/unordered_map,用set/map会TLE,因为前者的查询都为O(1),后者是O(logn)。