Leetcodee 76. 最小覆盖子串 双指针 哈希

地址 https://leetcode-cn.com/problems/minimum-window-substring/

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

注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
 
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"

示例 2:
输入:s = "a", t = "a"
输出:"a"

示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
 

提示:
1 <= s.length, t.length <= 105
s 和 t 由英文字母组成
 

进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?

解答
之前有谈过滑动窗口双指针的方法。
可以动态的扩大缩小连续的字符串,那么我们可以使用该方法获取最短长度满足涵盖目标字符串的子字符串。
如图


确认使用双指针后,还有一个问题需要解决,如何快速的判断当前双指针的范围内的字符串是否涵盖目标字符串。
可以使用哈希,快速的记录和查询当前字母是否包含在某段范围内。
扩大范围的时候 就把扩大包含的字母记录到哈希表中
缩小范围的时候 就把缩小抛弃的字母移出哈希表,或者说从哈希表中删除
缩小范围的操作

if (mm.count(s[l]) != 0) {
  //记录减1
  checkm[s[l]]--;
}
//移动左指针 缩小范围
l++;

扩大范围的操作

r++;
if (r < s.size() && mm.count(s[r]) != 0) {
  checkm[s[r]]++;
}

全部代码如下

class Solution {
public:
	unordered_map<char, int> mm;

	void init(const string& s) {
		for (auto& e : s) {
			mm[e]++;
		}
	}
	bool isEqual(unordered_map<char, int>& a, unordered_map<char, int>& b) {
		if (a.size() != b.size()) return false;

		for (auto& e : b) {
			if (e.second < a[e.first]) return false;
		}

		return true;
	}
	string minWindow(string s, string t) {
		init(t);
		int l = 0; int r = 0;
		unordered_map<char, int> checkm;
		if (mm.count(s[r]) != 0) {
			checkm[s[r]]++;
		}
		int ans = 999999; int ansl = -1; int ansr = -1;
		while (l < s.size() && r < s.size()) {
			if (isEqual(mm, checkm)) {
				//缩小范围
				if (ans > (r - l + 1)) {
					ans = r - l + 1; ansl = l; ansr = r;
				}
				if (l <= r) {
					if (mm.count(s[l]) != 0) {
						checkm[s[l]]--;
					}
					l++;
				}

			}
			else {
				//扩大范围
				r++;
				if (r < s.size() && mm.count(s[r]) != 0) {
					checkm[s[r]]++;
				}
			}
		}
		if (ansl == -1)return "";
		string ansstr = s.substr(ansl, ansr - ansl + 1);
		return ansstr;
	}
};

我的视频题解空间

posted on   itdef  阅读(64)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
历史上的今天:
2020-12-12 LeetCode 500. 键盘行 哈希
2020-12-12 LeetCode 1652. 拆炸弹 模拟
2019-12-12 poj 3468 A Simple Problem with Integers 线段树 题解《挑战程序设计竞赛》
2019-12-12 poj 2456 Aggressive cows 二分 题解《挑战程序设计竞赛》
2019-12-12 poj 1064 Cable master 二分 题解《挑战程序设计竞赛》
2014-12-12 c++11 stl 学习之 shared_ptr
2014-12-12 c++11 stl 学习之 pair

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示