[leetcode]Minimum Window Substring

Minimum Window Substring

Difficulty:Hard

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".

Note:
If there is no such window in S that covers all characters in T, return the empty string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

题目就是要在S中找到包含T中所有字符的最短子串,包含即可不需要顺序也相同,要求时间复杂度O(n)。

一开始想了几个方法复杂度都不是O(n),想了很久才想出一个办法。

先用一个数组compare记录T中所有字符的重复次数,即ASCii码从33到126的范围内计算,一共93种字符,例如T="aab<"就是2个a、1个b和一个<。

另一个数组match记录当前已满足的字符数,当match中所数都大于等于compare的时候就是找到了一个匹配

例外还有一个链表matchStr记录满足的字符的位置,当match中所有数没有大于等于compare的时候,其中match大于compare的数就是有多余的字符,应该尽可能的去除这些字符,但是只能从链表的头部开始去除。

找到了一个匹配后,通过删除去除满足字符的头,让匹配继续往后找。

string minWindow(string s, string t) {

	 int start = -1;
	 int end = s.size()+1;//end一开始大于S的size保证第一次匹配时能够赋值
	 vector<int> compare(93, 0);//需要满足的字符串个数
	 vector<int> match(93, 0);//已经满足的字符串个数
	 list<pair<int, char>> matchStr;//满足的字符串

	 for (int i = 0; i < t.size(); i++){ //计算每个字符需要的数量
		 compare[(int)(t[i]-33)]++;
	 }
	 for (int i = 0; i < s.size(); i++){
		 if (t.find(s[i]) != t.npos){//判断当前字符是否包含在T中

			 pair<int, char> p(i, s[i]);//加入满足队列
			 matchStr.push_back(p);

			 match[(int)(s[i] - 33)]++;//满足数增加

			 while (match[(int)(matchStr.front().second - 33)]>compare[(int)(matchStr.front().second - 33)]){//从头开始去除超出的满足字符
				 match[(int)(matchStr.front().second - 33)]--;
				 matchStr.pop_front();
			 }

			 bool isMatch = true;
			 for (int j = 0; j < match.size(); j++){//判断当前是否包含足够的字符
				 if (match[j] < compare[j])
					 isMatch = false;
			 }
			 if (isMatch){//包含足够的字符
				 if (i - matchStr.front().first < end - start){//是否比已找到的子串更短
					 start = matchStr.front().first;
				     end = i;
			     }

				 match[(int)(matchStr.front().second - 33)]--;//去除满足字符的头,让匹配继续往后找
				 matchStr.pop_front();

				 while (match[(int)(matchStr.front().second - 33)]>compare[(int)(matchStr.front().second - 33)]){//再从头开始去除超出的满足字符
					 match[(int)(matchStr.front().second - 33)]--;
					 matchStr.pop_front();
				 }

			 }
		 }
	 }

	 if (start < 0 )//通过start判断是否有找到匹配
		 return "";
	 else
		 return s.substr(start, end - start + 1);
 }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值