力扣热题100道-子串篇
字串
560.和为K的子数组
给你一个整数数组 nums
和一个整数 k
,请你统计并返回 该数组中和为 k
的子数组的个数 。
子数组是数组中元素的连续非空序列。
示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2
/**
思路:采用前缀和+哈希表解决
前缀和求出来后存到哈希表中,每个试着减去k如果有值说明有连续字串和为K
**/
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int n=nums.size();
vector<int> f(n);
f[0]=nums[0];
for(int i=1;i<n;i++){
f[i]=f[i-1]+nums[i];
}
unordered_map<int,int> hash;
hash[0]=1;
int res=0;
for(int i=0;i<n;i++){
res+=hash[f[i]-k];
hash[f[i]]++;
}
return res;
}
};
239.滑动窗口最大值
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
-1 3
示例 2:
输入:nums = [1], k = 1
输出:[1]
/**
思路:采用单调队列解决,队头为最大,每轮进行比较 i-k+1判断是否滑出窗口
队尾到队头 从小到大
来个值直接将小于它的全部干掉,塞到队尾
**/
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
//单调队列解决
deque<int> dq;
vector<int> res;
for(int i=0;i<nums.size();i++){
//单调队列
//有更大的把小的撵走,更大的下标肯定更优先选择,来小的塞到后面,防止前面大的滑出去了,小的可替
if(dq.size()&& i-k+1 > dq.front() ) dq.pop_front();
while(dq.size() && nums[i]> nums[dq.back()]) dq.pop_back();
dq.push_back(i);
if(i-k+1>=0) res.push_back(nums[dq.front()]);
}
return res;
}
};
76.最小覆盖字串
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
注意:
- 对于
t
中重复字符,我们寻找的子字符串中该字符数量必须不少于t
中该字符数量。 - 如果
s
中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
示例 2:
输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。
示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串
/*
思路:采用哈希表法,用两个哈希表 进行比较
如果遍历的串里存在t的值就让count++,然后进行窗口滑动即可
*/
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<int,int> hs;
unordered_map<int,int> ht;
for(auto c:t) ht[c]++;
int count = 0;
string res;
for(int i=0,j=0;i<s.size();i++){
hs[s[i]]++;
//只算到第一个找到的位置即可,后面不会再更新了
if(hs[s[i]]<=ht[s[i]]) count++;
while(hs[s[j]] > ht[s[j]]) hs[s[j++]]--;
if(count == t.size() && (res.empty() || i-j+1<res.size()) ){
res = s.substr(j,i-j+1);
}
}
return res;
}
};