字符串:滑动窗口

2021-10-02 每日一题 LeetCode

# 0003. 无重复字符的最长子串 (opens new window)

题目

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
1
2
3

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
1
2
3

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
1
2
3
4

提示:

  • 0 <= s.length <= 5 * 10^4
  • s 由英文字母、数字、符号和空格组成

解析

使用一个数组记录每个字符上次出现的位置,在遍历的同时移动窗口左边界,最后返回窗口长度的最大值即可。

代码

    # 0030. 串联所有单词的子串 (opens new window)

    题目

    给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

    注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words 中单词串联的顺序。

    解析

    维护一个长度为 m 个单词的滑动窗口,保证窗口内的单词与完全匹配 words。

    需要注意的是,words 内的单词长度相同,因此可以按照单词的长度来移动滑动窗口,最终通过一个额外的 cnt 变量来统计两个哈希表的匹配单词数即可。

    代码

    class Solution {
    public:
        vector<int> findSubstring(string s, vector<string>& words) {
            vector<int> ans;
            if (words.empty()) return ans;
    
            int n = s.length(), m = words.size(), w = words[0].length();
    
            // 记录目标串每个单词应出现的次数
            unordered_map<string, int> total;
            for (int i = 0; i < words.size(); i++) {
                total[words[i]]++;
            }
    
            for (int i = 0; i < w; i++) {
                unordered_map<string, int> window;
                int cnt = 0;
                for (int j = i; j + w <= n; j += w) {
                    // 超过目标串长度,需要去除头部的字符串
                    if (j >= i + m * w) {
                        string word = s.substr(j - m * w, w);
                        window[word]--;
                        if (window[word] < total[word]) cnt--;
                    }
                    // 新增的字符串
                    string word = s.substr(j, w);
                    window[word]++;
                    if (window[word] <= total[word]) cnt++;
    
                    // 完全匹配,添加结果
                    if (cnt == m) ans.push_back(j - (m - 1) * w);
                }
            }
            return ans;
        }
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

    # 0076. 最小覆盖子串 (opens new window)

    题目

    给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

    注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

    解析

    使用双指针 i、j,其中 i 遍历字符串 s,j 用来寻找满足条件的位置,使得 j 到 i 的字符串刚好包含字符串 t 的所有字符。

    代码

    class Solution {
    public:
        string minWindow(string s, string t) {
            unordered_map<char, int> hs, ht;
            for (int i = 0; i < t.length(); i++) ht[t[i]]++;
    
            string ans;
            for (int i = 0, j = 0, cnt = 0; i < s.length(); i++) {
                // 添加当前字符,更新有效字符数量
                if (++hs[s[i]] <= ht[s[i]]) cnt++;
                
                // j 向前移动,去除冗余字符
                while (j <= i && hs[s[j]] > ht[s[j]]) hs[s[j++]]--;
    
                // 完全覆盖,更新 ans
                if (cnt == t.length()) {
                    if (ans.empty() || ans.length() > i - j + 1) {
                        ans = s.substr(j, i - j + 1);
                    }
                }
            }
            return ans;
        }
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    # 0159. 至多包含两个不同字符的最长子串 (opens new window)

    题目

    解析

    代码

    # 0163. 缺失的区间 (opens new window)

    题目

    解析

    代码

    # 0228. 汇总区间 (opens new window)

    题目

    解析

    代码

    # 0239. 滑动窗口最大值 (opens new window)

    题目

    解析

    代码

    # 0340. 至多包含 K 个不同字符的最长子串 (opens new window)

    题目

    解析

    代码

    # 0395. 至少有 K 个重复字符的最长子串 (opens new window)

    题目

    解析

    代码

    # 0424. 替换后的最长重复字符 (opens new window)

    题目

    解析

    代码

    # 0475. 供暖器 (opens new window)

    题目

    解析

    代码

    # 0481. 神奇字符串 (opens new window)

    题目

    解析

    代码

    # 0565. 数组嵌套 (opens new window)

    题目

    解析

    代码

    Last Updated: 2023-01-28 4:31:25