LeetCode Minimum Window Substring

126 篇文章 0 订阅
24 篇文章 0 订阅

路走了一半,后半场的第一题,感觉有点似曾相识,细节都忘了。用了开始的第一种方法尝试了一下,也改了几次呢,最终还是败在time limit exceeded。this feeling is not so bad, just like meeting  a good-looking girl that turn you down for the first time, which just increase the feeling of adoration for her thinking she is more than beautiful outside, but   gorgeous inside.

第一种方法:还是最原始的思想,开辟一个长度和T一样的数组,记录每个字符出现的位置。数组中的最大位置和最小位置的差就是当前长度。然后找最小位置的那个字符出现的下一个位置,用其值更新数组中原来的位置,此时重新计算数组中的最小值和最大值,看当前长度是不是小于原来求得的最小长度,若小于的话更新最小长度。不断的迭代,直到找到某个位置返回-1(因为用find函数)说明找到头了,退出循环。当然这样处理时间肯定不是O(N+M),而是O(N)*O(M),做了优化,就是用set来代替数组,因为这样就不用花O(M)的时间找最大最小值了。其实时间是花在插入时了,总时间复杂度还是O(N)*O(log(M))。只贴优化的吧,做了几组测试,都通过了。相信是正确的。

string minWindow2(string S,string T) {
	int lenT = T.length();
	int lenS = S.length();
	if(lenS==0||lenT==0||lenT>lenS)
		return string("");
	set<int> posSet;
	int temppos;
	for (int i=0;i<lenT;i++)
	{
		temppos=S.find(T[i],0);
		while(posSet.find(temppos)!=posSet.end())//temppos could not be in the posSet,case of "aa"  "aa"
		{
			temppos = S.find(T[i],temppos+1);
		}
		if(temppos==-1)
			return string("");
		posSet.insert(temppos);
	}
	if(lenT>lenS)
		return S;
	int distance,mindis = lenS+1,minStart=0,minEnd=lenT;
	while(1)
	{
		set<int>::reverse_iterator iter_end = posSet.rbegin();
		distance = *iter_end - *(posSet.begin()) + 1;
		if(distance<mindis)
		{
			mindis = distance;
			minStart = *(posSet.begin());
			minEnd = *iter_end;
		}
		temppos = S.find(S[*(posSet.begin())],*(posSet.begin())+1);
		while(posSet.find(temppos)!=posSet.end())
		{
			temppos = S.find(S[temppos],temppos+1);//temppos = S.find(T[i],temppos+1);
		}
		if(temppos==-1)
			break;
		posSet.erase(posSet.begin());
		posSet.insert(temppos);
	}
	return S.substr(minStart,minEnd-minStart+1);
}
测试用例

int _tmain(int argc, _TCHAR* argv[])
{
	string S="abc";//"aa";//"ab";//"abbbb";//"ADOBECODEBANC";//"acbbaca";//"cabefgecdaecf";//"bba";//
	string T="cba";//"aa";//"a";//"aa";//"ABC";//"aba";//"cae";//"ab";//
	cout<<minWindow2(S,T)<<endl;
	S="aa";//"ab";//"abbbb";//"ADOBECODEBANC";//"acbbaca";//"cabefgecdaecf";//"bba";//
	T="aa";//"a";//"aa";//"ABC";//"aba";//"cae";//"ab";//
	cout<<minWindow2(S,T)<<endl;
	S="ab";//"abbbb";//"ADOBECODEBANC";//"acbbaca";//"cabefgecdaecf";//"bba";//
	T="a";//"aa";//"ABC";//"aba";//"cae";//"ab";//
	cout<<minWindow2(S,T)<<endl;
	S="ADOBECODEBANC";//"acbbaca";//"cabefgecdaecf";//"bba";//
	T="ABC";//"aba";//"cae";//"ab";//
	cout<<minWindow2(S,T)<<endl;
	S="acbbaca";//"cabefgecdaecf";//"bba";//
	T="aba";//"cae";//"ab";//
	cout<<minWindow2(S,T)<<endl;
	S="cabefgecdaecf";//"bba";//
	T="cae";//"ab";//
	cout<<minWindow2(S,T)<<endl;
	S="bba";//
	T="ab";//
	cout<<minWindow2(S,T)<<endl;
	system("pause");
	return 0;
}
下面的方法是看别人的思路  http://www.cnblogs.com/lichen782/p/leetcode_minimum_window_substring_3.html

自己写的代码,写代码时各种错误呀,提交了十来遍,主要是程序逻辑问题,还有考虑不周。这真是锻炼基本功呀。下面是我的第一次 提交通过的代码,看似简单,我可在while,for,if里里外外,前前后后 迷糊了好久。

string minWindow3(string S,string T) {
	int lenT = T.length();
	int lenS = S.length();
	if(lenS==0||lenT==0||lenT>lenS)
		return string("");
	map<char,int> needFound;
	map<char,int> hasFound;
	for (int i=0;i<lenT;i++)
	{
		needFound[T[i]]++;
	}
	int begin=0,end=0;
	int count=0;
	int distance,mindis=lenS+1;
	int minStart=0,minEnd=lenS;
	while(end<lenS&&begin<lenS)
	{
		while(end<lenS&&needFound[S[end]]==0){
			end++;
		}
		if(end==lenS)
			break;
		hasFound[S[end]]++;
		if (hasFound[S[end]]<=needFound[S[end]])
		{
			count++;
		}
		while(count==lenT&&hasFound[S[begin]]>needFound[S[begin]]||needFound[S[begin]]==0)
		{
			hasFound[S[begin]]--;
			begin++;
		}
		if (count==lenT)
		{
			distance = end - begin + 1;
			if(distance<mindis)
			{
				mindis = distance;
				minStart = begin;
				minEnd = end;
			}
		}
		end++;		
	}
	if(count==lenT)
		return S.substr(minStart,minEnd-minStart+1);
	else
		return string("");
}
终于AC了,长舒一口气,想看一下提交了多少次,确被运行时间吸引了,652ms,可不少,这还O(N)呢,于是试了试别人的  http://blog.csdn.net/doc_sgl/article/details/12395759 这个大神的,结果是84ms。怎么回事呢?我倒没仔细看他的程序逻辑,只是看了他没用map,用数组了,所以我就先从这试试吧,结果出来了。

就是上面的代码把map改成数组就行了,操作方式都不用变。贴不贴都行,为了完整,还是贴上吧。

string minWindow4(string S,string T) {
	int lenT = T.length();
	int lenS = S.length();
	if(lenS==0||lenT==0||lenT>lenS)
		return string("");
	int needFound[256]={0};
	int hasFound[256]={0};
	for (int i=0;i<lenT;i++)
	{
		needFound[T[i]]++;
	}
	int begin=0,end=0;
	int count=0;
	int distance,mindis=lenS+1;
	int minStart=0,minEnd=lenS;
	while(end<lenS&&begin<lenS)
	{
		while(end<lenS&&needFound[S[end]]==0){
			end++;
		}
		if(end==lenS)
			break;
		hasFound[S[end]]++;
		if (hasFound[S[end]]<=needFound[S[end]])
		{
			count++;
		}
		while(count==lenT&&hasFound[S[begin]]>needFound[S[begin]]||needFound[S[begin]]==0)
		{
			hasFound[S[begin]]--;
			begin++;
		}
		if (count==lenT)
		{
			distance = end - begin + 1;
			if(distance<mindis)
			{
				mindis = distance;
				minStart = begin;
				minEnd = end;
			}
		}
		end++;		
	}
	if(count==lenT)
		return S.substr(minStart,minEnd-minStart+1);
	else
		return string("");
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值