力扣热题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;
    }
};