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"
.
Note:
If there is no such window in S that covers all characters in T, return the emtpy string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
题目的意思是说,要在S中找一个最短的子串,该子串包含了T中的所有字符,如上面所示用暴力法肯定是能够求出来的,思路为:用一个双重循环 从以S[0]开始的子串开始,求一个最短的,并用一个变量保存该值,然后求一个以S[1]开始的子串,并跟新变量的值。
下面介绍一种不用暴力法的算法
讲的是用一个hash表来存放字符串,然后动态的改变一个窗口,跟新而得到结果,这个有点类似
具体如下:
首先定义两个数组,一个为totalnumber[]表示T中字母所需要的次数
一个为aredyfind[] 表示遍历过程中已经找到T中字母次数
totalnumber初始化为 遍历 T 然后 totalnumber[ T[ i ] ] ++ ,表示统计T中每个字母出现的次数
初始用两个指针(i,start) 指向 S[0] ,然后 i 一直 后面遍历,直到找到一个合适地址,该地址到start刚好是一个拥有所有T中字母的子串 (并不一定最优)
此时已经找到了一个以 start开始 的最小窗口
缩减窗口: 将start 开始 但是 并不属于T中的字母删除 start++ 直到 start处的字母属于T ,当前已经找到一个最优的(satrt开始 i结束) 记录下来
然后start++ ,此时需要主要的是,由于上面已经找到一个当前最优的,那么 start++之后 必然会将一个属于T的字母删除了, 那么 需要i++来寻找那个字母了
所以又用i来遍历
代码 如下:
<span style="font-size:18px;">class Solution { public: string minWindow(string S, string T) { int totalnumber[256]={0}; int aredyfind[256]={0}; int count=0;//用来表示当前已经找到的总字符,如果都找到,count为T.length() int i,start; int winstart=-1; int winend=S.length(); for(i=0;i<T.size();i++) { totalnumber[T[i]]++; } for(i=0,start=0;i<S.size();i++) { if(totalnumber[S[i]]!=0) //这里表示字符S[i]属不属于T,如果不属于T那么直接跳过 { aredyfind[S[i]]++; if(aredyfind[S[i]]<=totalnumber[S[i]]) count++; if(count==T.length()) //表示已经找到了一个合法的窗口 { while(totalnumber[S[start]]==0||aredyfind[S[start]]>totalnumber[S[start]]) //这里判断start处的字符属不属于T或者属于T但是重复出现了,两种情况都是要缩小窗口的 { if(aredyfind[S[start]]!=0) aredyfind[S[start]]--; start++; } if(winend-winstart>i-start) { winend=i; winstart=start; } aredyfind[S[start]]--; //上面表示已经找到了一个start开始 i结束的当前最优,然后start++,此时必然有字母被删除了,所以回到开始i出循环,i往后遍历来寻找哪个被删除的字母 start++; count--; } } } return winstart==-1?"":S.substr(winstart,winend-winstart+1); } };</span>