NO 76 Minimum Window Substring

/*
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC".

给定字符串S和字符串T,找到S中的最小窗口,其中将包含复杂度O(n)中T中的所有字符。

例如,
S =“ADOBECODEBANC”
T =“ABC”
最小窗口为“BANC”。
*/

滑动窗的暴力做法:

string minWindow(string s, string t) {
		if (s.compare(t) == 0) return s;
		int lens = s.size();
		int lent = t.size();
		map<char, int> mt;//存储t中的映射关系
		map<char, int> m0;//存储t中的映射关系,置零
		for (int i = 0; i < lent; i++){
			if (mt.count(t[i]) == 0) {
				mt.insert(pair<char, int>(t[i], 0));
				m0.insert(pair<char, int>(t[i], 0));
			}
			mt[t[i]]++;
		}
		//构造m作为窗的判断条件
		map<char, int> m = mt;
		//截取的字符串长度,用作判断是否为最小窗口
		int len = INT_MAX;
		//结果
		string minString;
		//有效键值对个数
		int cnt = m.size();
		//窗的终点、起点
		int end = 0;
		int start;
		bool flag = false;
		for (end; end < lens; end++){
			//若含有键,m中值--
			if (m.count(s[end]) != 0){
				m[s[end]]--;
				//若该键对应值为0,有效键值对个数--
				if (m[s[end]] == 0){
					cnt--;
				}
			}
			//当有效键值对个数为0时,end为窗的终点
			if (cnt == 0){
				//由终点往前找起点
				start = end;
				//避免值为负数的情况
				m = m0;
				//起点找到的判断条件是有效键值对的个数恢复到t中有效键值对的个数
				while (cnt != mt.size()){
					//如果包含该键
					if (m.count(s[start]) != 0){
						//值++
						//如果值恢复为t中的值,有效键值对个数++
						if (++m[s[start]] == mt[s[start]])
						{
							cnt++;
						}
					}
					//如果有效键值对的个数恢复到了t中有效键值对的个数
					//找到了窗的起点start
					if (cnt == mt.size()){
						//如果此时的窗比之前的小,保存窗字符串
						if (len > end - start + 1){
							len = end - start + 1;							
							minString = s.substr(start,len);						
						}
						//释放start处的值
						//不管是否为最小窗,完成了一次start,end的截取后
						flag = true;
						m = m0;
						m[s[start]]++;
					}
					//未找到start,继续向前查找
					start--;
				}				
			}
			if (flag){
				//释放后有效键值对个数为1
				cnt = 1;
				flag = false;
			}
		}
		return minString;
	}
能解决问题,但是超时了。

讨论中的做法如下,

关键还是有效键值对个数这个值

	string minWindow(string s, string t){
		if (s.compare(t) == 0) return s;
		int lens = s.size();
		int lent = t.size();
		map<char, int> mt;//存储t中的映射关系
		for (int i = 0; i < lent; i++){
			if (mt.count(t[i]) == 0) {
				mt.insert(pair<char, int>(t[i], 0));
			}
			mt[t[i]]++;
		}
		int cnt = mt.size();
		int end = 0;
		int start = 0;
		int head = 0;
		int len = INT_MAX;
		for (end; end < lens; end++){
			char tem = s[end];
			if (mt.count(tem) != 0){
				mt[tem]--;
				if (mt[tem] == 0){
					cnt--;
				}
			}
			while (cnt == 0){
				char tem = s[start];
				if (mt.count(tem) != 0){
					mt[tem]++;
					if (mt[tem]>0){
						cnt++;
						if (end - start+1 < len){
							len = end - start+1;
							head = start;
						}
					}
				}
				start++;
			}
		}
		if (len == INT_MAX) return "";
		return s.substr(head, len);
	
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值