76.最小覆盖子串
题目
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
数据范围
m == s.length
n == t.length
1 <= m, n <= 105
s
和t
由英文字母组成
分析
滑动窗口,当我们第一次找到t
在s
中的位置时,若长度为len
,则后续的结果只需要考虑小于len
的情况即可,设置一个长度为len
的窗口,每次将窗口向右滑动,r
指针为右边界,每次向右滑动一格,l
指针为左边界,用于缩小滑动窗口,写一个check()
函数判断窗口内的字符串是否包含t
,若包含,则用l
缩小窗口的即可。check()
函数可以只使用一个map
,在刚开始预处理t
字符串的字符频数,s[l]
在t
中则对应字符频数减1
,若频数均<=0
则说明包含t
。
代码
class Solution {
public:
map<char, int> cnt;
bool check() {
for(auto [k, v] : cnt) {
if(v > 0) return false;
}
return true;
}
void print() {
for(auto [k, v] : cnt) {
cout << k << " " << v << " ";
}
cout << endl;
}
string minWindow(string s, string t) {
if(s.size() < t.size()) return "";
int l = 0, r = 0;
for(int i = 0; i < t.size(); i ++ ) {
cnt[t[i]] ++ ;
}
int len = 0x3f3f3f3f;
int pos = -1;
while(r < s.size()) {
if(cnt.find(s[r]) != cnt.end()) {
cnt[s[r]] -- ;
}
bool flag = check();
while(check() && l <= r) {
if(r - l + 1 < len) {
len = r - l + 1;
pos = l;
}
if(cnt.find(s[l]) != cnt.end()) cnt[s[l]] ++ ;
l ++ ;
}
r ++ ;
}
if(pos == -1) return "";
return s.substr(pos, len);
}
};
15.三数之和
题目
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为 0
且不重复的三元组。
数据范围
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
分析
本题实际是两数之和的进阶版,最暴力的方法就是使用三重循环,复杂度为O(N^3)
,由于本题和两数之和有点关系,很容易可以发现后面的两重循环可以使用一个双指针算法进行简化,思路和两数之和一模一样。本题要求三元组不重复,思考一下什么情况会重复,双指针l
和r
表示边界,举个例子-3、1、1、2
,指针l
遍历第一个1
和第二个1
都会产生相同的答案,若要消除这种情况,在遍历l
时只要判断nums[l]
和nums[l-1]
是否相同即可,若相同则上一次循环已经考虑过这种情况,直接continue
,同时与这种情况对应的是遍历r
时两个数相同,此时判断nums[r]
和nums[r+1]
是否相同即可
代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
int n = nums.size();
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); i ++ ) {
if(i && nums[i] == nums[i - 1]) continue;
int l = i + 1, r = n - 1;
while(l < r) {
if(l > i + 1 && nums[l] == nums[l - 1]) {
l ++ ;
continue;
}
if(r < n - 1 && nums[r] == nums[r + 1]) {
r -- ;
continue;
}
int t = nums[l] + nums[r] + nums[i];
if(t > 0) {
r -- ;
} else if(t < 0){
l ++ ;
} else {
res.push_back({nums[i], nums[l], nums[r]});
l ++ ;
r -- ;
}
}
}
return res;
}
};