题解 | #牛群名字覆盖#
牛群名字覆盖
https://www.nowcoder.com/practice/e6cef4702e7841f59cf47daf9bafb241
大家好,我是开车的阿Q,自动驾驶的时代已经到来,没时间解释了,快和阿Q一起上车。作为自动驾驶系统工程师,必须要有最好的C++基础,让我们来一起刷题吧。
题目考察的知识点
这道题目主要考察了字符串处理、滑动窗口、哈希表的运用。
题目解答方法的文字分析
我们可以使用滑动窗口的思想来解决这个问题。
具体步骤如下:
- 首先,我们建立一个哈希表 targetFreq 来存储指定英文字母的频次。
- 然后,使用双指针构建滑动窗口,左指针 left 和右指针 right,初始时都指向字符串 s 的第一个字符。
- 初始化一个变量 minLen 用于记录最小子串的长度,一个变量 minSubstr 用于记录最小子串,以及一个变量 found 用于记录是否找到了包含所有指定英文字母的子串。
- 开始滑动窗口,将右指针 right 向右移动,同时更新哈希表 currFreq 来记录当前窗口内各个字符的频次。
- 当 currFreq 包含了 targetFreq 的所有字符且频次不少于 targetFreq 时,我们尝试将左指针 left 向右移动,以缩小子串长度,同时更新哈希表 currFreq。
- 每次右指针 right 移动时,我们检查当前子串长度是否小于 minLen,如果是,则更新 minLen 和 minSubstr。
- 最终,当滑动窗口结束时,minSubstr 就是最短的名字序列,使得这些名字能够包含所有指定的英文字母。
本题解析所用的编程语言
本题解析所用的编程语言是 C++。
完整且正确的编程代码
#include <string>
#include <unordered_map>
using namespace std;
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char, int> targetFreq; // 存储指定英文字母的频次
for (char c : t) {
targetFreq[c]++;
}
unordered_map<char, int> currFreq; // 当前窗口内各个字符的频次
int left = 0, right = 0; // 滑动窗口的左右指针
int minLen = INT_MAX; // 最小子串长度
string minSubstr = ""; // 最小子串
int found = 0; // 是否找到了包含所有指定英文字母的子串
while (right < s.length()) {
char c = s[right];
currFreq[c]++;
// 当 currFreq 包含了 targetFreq 的所有字符且频次不少于 targetFreq 时
while (found < targetFreq.size() && freqMet(currFreq, targetFreq)) {
int len = right - left + 1;
if (len < minLen) {
minLen = len;
minSubstr = s.substr(left, len);
}
char leftChar = s[left];
currFreq[leftChar]--;
if (currFreq[leftChar] < targetFreq[leftChar]) {
found--;
}
left++;
}
if (currFreq[c] == targetFreq[c]) {
found++;
}
right++;
}
return minSubstr;
}
private:
bool freqMet(const unordered_map<char, int>& currFreq, const unordered_map<char, int>& targetFreq) {
for (const auto& entry : targetFreq) {
if (currFreq.find(entry.first) == currFreq.end() || currFreq.at(entry.first) < entry.second) {
return false;
}
}
return true;
}
};
阿Q的题解 文章被收录于专栏
阿Q秋招刷过的题

