LeetCode 热题 100 | 子串

目录

[1 560. 和为 K 的子数组](#1 560. 和为 K 的子数组)

[2 239. 滑动窗口最大值](#2 239. 滑动窗口最大值)

[3 76. 最小覆盖子串](#3 76. 最小覆盖子串)


菜鸟做题第二周,语言是 C++

1 560. 和为 K 的子数组

题眼:"子数组是数组中元素的连续非空序列。"

解决本问题的关键就在于如何翻译问题。子数组 s 的和可以看作数组 i 的和减去数组 j 的和,这样就把 "求子数组的和" 转换为了 "前缀和之间的差"。如下图所示:

解题思路:

  1. 遍历数组,计算所有前缀和 sum(i),并存入哈希表中
  2. 同时查看哈希表中是否存在前缀和 sum(j) 等于 sum(i) - k
cpp 复制代码
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> hash;

        int pre = 0, ans = 0;
        for (auto num:nums) {
            pre += num;
            if (pre == k) ++ans;
            if (hash.find(pre - k) != hash.end()) {
                ans += hash[pre - k];
            }
            ++hash[pre];
        }
        return ans;
    }
};

说明:这句代码是为了避免遗漏本身前缀和就等于 k 的情况

cpp 复制代码
if (pre == k) ++ans;

官方题解一开始就给哈希表插入了 (0, 1),应该就是为了解决这个问题,但我没有照做。

2 239. 滑动窗口最大值

主要看你会不会优先队列。。。

解题思路:

  1. 初始化:插入前 k 个数字,队列头就是最大值
  2. 一格一格地右移窗口,并弹出队列头
  3. 若队列头的下标处在窗口内,则它就是窗口内的最大值
  4. 若队列头的下标处在窗口外,则继续弹出,直到处在窗口内
cpp 复制代码
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int n = nums.size();
        priority_queue<pair<int, int>> q;

        for (int i = 0; i < k; ++i) {
            q.emplace(nums[i], i);
        }

        vector<int> ans = {q.top().first};
        for (int i = k; i < n; ++i) {
            q.emplace(nums[i], i);
            while (q.top().second <= i - k) {
                q.pop();
            }
            ans.push_back(q.top().first);
        }

        return ans;
    }
};

3 76. 最小覆盖子串

读懂题意很重要。。。

题目只要求当前窗口内的字母能够拼出字符串 t 即可,没有要求字母数量要一致。因此,判断能否覆盖的方法如下:

cpp 复制代码
bool succeed() {
    for (auto t:tCount) {
        if (sCount[t.first] < t.second) {
            return false;
        }
    }
    return true;
}

其中,tCount 和 sCount 均为哈希表。tCount 记录的是 t 的字母数量,sCount 记录的是 s 的字母数量。这里只要求 sCount 中相应字母的数量比 t 的多即可,而不一定要相等。

解题思路:

  1. 首先移动右指针 right 使得窗口能够覆盖子串
  2. 然后移动左指针 left 直到窗口刚好不能覆盖子串
  3. 再移动右指针 right 使得窗口能够覆盖子串
  4. 循环往复(期间要维护最小长度和起始位置)

思路说明图:

可以类比为一只爬行的毛毛虫。首先,毛毛虫伸头,使得窗口能够覆盖子串 "ABC";然后,毛毛虫收尾,使得窗口刚好不能覆盖子串 "ABC";毛毛虫再伸头,使得窗口能够再次覆盖子串 "ABC";以此类推。

cpp 复制代码
class Solution {
public:
    unordered_map<char, int> sCount, tCount;

    bool succeed() {
        for (auto t:tCount) {
            if (sCount[t.first] < t.second) {
                return false;
            }
        }
        return true;
    }

    string minWindow(string s, string t) {
        int sLen = s.size(), tLen = t.size();
        int minStart = 0, minLen = sLen;
        string ans;
        int flag = 0;

        if (sLen < tLen) return "";

        for (int i = 0; i < tLen; ++i) {
            ++tCount[t[i]];
        }

        int left = 0, right = 0;
        while (right < sLen) {
            // 毛毛虫伸头
            if (tCount.find(s[right]) != tCount.end()) {
                ++sCount[s[right]];
            }
            ++right;

            // 毛毛虫收尾
            while (succeed()) {
                flag = 1;
                if (tCount.find(s[left]) != tCount.end()) {
                    --sCount[s[left]];
                }
                if (minLen > right - left) {
                    minLen = right - left;
                    minStart = left;
                }
                ++left;
            }
        }

        // 处理结果
        if (flag) {
            for (int i = minStart; i < minStart + minLen; ++i) {
                ans.push_back(s[i]);
            }
        }

        return ans;
    }
};

说明:每次做如下判断是因为我们只关心子串中含有的字母的个数

cpp 复制代码
if (tCount.find(s[right]) != tCount.end()) {
    ++sCount[s[right]];
}
相关推荐
我是哈哈hh41 分钟前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
Tisfy1 小时前
LeetCode 2187.完成旅途的最少时间:二分查找
算法·leetcode·二分查找·题解·二分
Mephisto.java1 小时前
【力扣 | SQL题 | 每日四题】力扣2082, 2084, 2072, 2112, 180
sql·算法·leetcode
robin_suli1 小时前
滑动窗口->dd爱框框
算法
丶Darling.1 小时前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树
labuladuo5201 小时前
Codeforces Round 977 (Div. 2) C2 Adjust The Presentation (Hard Version)(思维,set)
数据结构·c++·算法
jiyisuifeng19912 小时前
代码随想录训练营第54天|单调栈+双指针
数据结构·算法
꧁༺❀氯ྀൢ躅ྀൢ❀༻꧂2 小时前
实验4 循环结构
c语言·算法·基础题
新晓·故知2 小时前
<基于递归实现线索二叉树的构造及遍历算法探讨>
数据结构·经验分享·笔记·算法·链表
总裁余(余登武)2 小时前
算法竞赛(Python)-万变中的不变“随机算法”
开发语言·python·算法