LeetCode76——Minimum Window Substring

本文介绍了LeetCode76问题的解决思路,通过维护一个Map来寻找包含目标串所有字符的最短子串。在过程中,不断调整开始和结束索引,优化窗口大小,避免重复字符。详细讲解了判断和移动索引的策略,以及如何处理重复字符的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode76——Minimum Window Substring

以前似乎做过类似的,点了LeetCode类似题想起来了(这点把不同类型的题目分类真心不错)

好了,跟LeetCode30——Substring with Concatenation of All Words很相似,需要维护一个Map。

当时做这题的时候就感觉自己做得非常不智能,有点像朴素的字符串的模式匹配,效率比较低。

做这题的时候也比较吃力。

言归正传。

--------------------------------------------------------------------------------------------

这题的意思是:

从母串S中找到这样一个子串W,这个子串包含目标T串中的所有字符,并且该子串的长度最短。


思路:

维护两个索引Start 和 End(初值都为0),分别标识 子串W(这里表示Window)的开始位置和结束位置。

下面关键就是判断何时这两个索引要变化。


1.首先如果没有找到map中的单词,End++,继续往后找。


2.如果map中的字母还没找完,且找到了当前字母,则map中当前单词对应的value--(表示找到一个)。


3.当然可能有重复字母,即value减为负了,这样找出来的window包含多余重复字母肯定不是最优,所以我们要记录找到字母个数。


4.一旦找满单词,这个时候Start到End的位置肯定是包含目标T串所有字符的子串W(即Window)


5.但是这个window不是最优的,我们要对start++,排除不在map中的字符(其实就是让Start越过步骤1中跳过的字符),缩小window大小


6.还有需要优化的地方,就是当window中出现重复的字符,这时,map中该字符的value为负了,我们可以向前移动start。


关于第6点,比如说:

母串ABCDDDDDDDA

目标串ABC

那么当End移动到最后一个A时,Start只能停在第一个A处(为了保证Window中包含ABC三个字母)

而当End移动到最后一个A时,此时Window中多一个A(Map中A的值减为负了),这个时候Start就可以往前移动一下,做一步优化。


根据上述6点,代码就很容易了:


class Solution{
public:
	string minWindow(string s, string t){
	    if(s.size()<t.size())
	        return "";
		map<char, int>chrMap;//保存最初的字母
		for (int i = 0; i < t.size(); i++)
		{
			chrMap[ t[i] ]++;
		}
		int start = 0;
		int end = 0;
		int count = 0;//window中包含所需字符的数量
		int minWindowLen = INT_MAX;
		int curWindow;//当前window大小
		int minStart = 0;//当前window最小值时start的位置
		int minEnd = 0;//当前window最小值时end的位置
		map<char, int>tempMap(chrMap.begin(), chrMap.end());//临时map,用于计算
		while (end < s.size())
		{
			if (tempMap.find(s[end]) == tempMap.end())
			{
				end++;
				continue;
			}
			tempMap[s[end]]--;
			if (tempMap[s[end]] >= 0)
				count++;
			if (count == t.size())//找满一次窗口
			{
				while (start != end)
				{
					if (chrMap.find(s[start]) == chrMap.end())//start不在T的map里面
					{
						start++;
						continue;
					}
					if (tempMap[s[start]] < 0)//window中对于同一字符找重了,此时要向前移动并且补上
					{
						tempMap[s[start]]++;
						start++;
						continue;
					}
					else
						break;
				}
				curWindow = end - start + 1;
				//curWindow = min(curWindow, minWindowLen);
				if (curWindow < minWindowLen)
				{
					minWindowLen = curWindow;
					minStart = start;
					minEnd = end;
				}
			}
			end++;
		}
		if (minWindowLen == INT_MAX)
			return "";
		return s.substr(minStart, minWindowLen);
	}
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值