[Algorithm series 22] contains t all elements of the Kid's window

Source: Internet
Author: User

Title Description

Given a set of T and string s that contains a series of characters, find the smallest window in the string s, which must contain all the characters in T.
For example
S = "Adobecodebanc"
T = "ABC"

The minimum window is "BANC"

Analysis

This is an interesting question, there are many ways to solve this interesting problem, the best way is very simple and beautiful.
In this article, I first explained a method that I thought of when I first met the problem. My first method is a bit complicated and not the best solution (time complexity is O (NLGM)). Later in this article, I present a better method, with the time Complexity O (N).
Hint:
Using the example above in S = "Adobecodebanc", s = "ABC", we can easily find the first window "Adobec", which contains all the elements in T. Another possible candidate is "Adobecodeb A". In fact, we should skip this because there is a sub-window "Codeba" in this window that is short and satisfies the constraints. One of the last windows to consider is "BANC", which is also the smallest window.

To solve this problem effectively, here are two key points to consider:

我们如何确定一个特定的窗口包含T ?(最理想的情况是O(1)时间)。我们如何有效的选择所有窗口?(最理想的情况是不包括含有子窗口的那些窗口)。

We absolutely need the help of hash table (hash table). The hash table can tell us whether a character is in T in O (1) time.

O (N lg M) method :

When I first encountered this problem, I thought of another table, where the characters last appeared. That is, when I first saw the character ' A ', I recorded its position at 0. Every time I see ' A ', I use a new position instead of its original position. Although this method is very simple, the flaw is also obvious. Notice that T does not contain duplicate characters? If T contains duplicate characters, such as "AABC", this method cannot be used.

In this case, the remedy is to maintain a queue (not a table), and each character in t corresponds to a queue (for example: Character a corresponds to a queue, character B corresponds to a queue ...). )。 For example, suppose t = "AABC", when you first encounter "a", place it in the "a" queue (initially empty). When you encounter "a" again, put its position at the end of the "a" queue. The third time you encounter "a", The first element pops up, and the location of the "a" is placed at the end of the "a" queue. With pop-up elements, we don't include those windows that contain child windows. This approach is effective, but the difficulty is twofold:

我们没有办法从队列本身直接确定窗口的开始和结束位置。一个最自然的方法是扫描整个队列得到最小值和最大值。我们如何确定这个窗口是否满足约束条件呢?我们不得不扫描整个队列来检查所有队列大小总和是否等于T的长度。

My approach to solving this problem is to maintain a sorted map that maps to every character. This allows us to obtain the position of the minimum and maximum values in O (1) time. But it will take extra time to do so. Every time you pop an element out of the queue, you have to update the map by deleting the corresponding element and inserting a new element. To check whether the window satisfies the constraint, we must look at the size of the map, and if the size of the map is equal to the length of T, it means to find a valid window.

The time complexity of this method is O (n lg M), where n is the length of s, and M is the length of T. The extra LgM is due to the extra cost of deleting and inserting an element in the map, with each worst case cost O (LgM) time. (Note that M is the maximum size of the map.) )

/*---------------------------------------------* Date: 2015-02-24* sjf0115* title: 22. The kid's window containing all the elements of T * Source: Algorithm Series * Blog:- ----------------------------------------------*/#include <iostream>#include <map>#include <queue>#include <climits>#include <algorithm>using namespace STD;BOOLMinwindow (stringSstringTint&startwin,int&endwin) {intSlen = S.size ();intTlen = T.size ();if(Slen <=0|| Tlen <=0){return false; }//if    //Store the total number of different characters in T    intneedfind[ the] = {0}; for(inti =0; i < tlen;++i) {++needfind[t[i]]; }//for    //The element not in T is set to-1     for(inti =0; I < the; ++i) {if(Needfind[i] = =0) {Needfind[i] =-1; }//if}//for    intMinwinlen = Int_max;//queue array, each of the different characters corresponds to a queue     Queue<int>q[ the];The first element and the last element indicate the start and end position of the window     map<int,char>MintVal for(inti =0; i < slen;++i) {val = s[i];//Skip elements that are not in T        if(Needfind[val] = =-1) {Continue; }//id        //character into queue        if(Q[val].size () < Needfind[val])            {Q[val].push (i);        M[i] = val; }//if        //Replace the characters in the queue to update the corresponding elements in the map        Else{intIdxtoerase = Q[val].front (); map<int,char>:: Iterator it = M.find (idxtoerase);            M.erase (IT);            M[i] = val;            Q[val].pop ();        Q[val].push (i); }//else        if(m.size () = = Tlen) {intEnd = M.rbegin ()->first;intStart = M.begin ()->first;intWinlen = End-start +1;if(Winlen < Minwinlen)                {Minwinlen = Winlen;                Startwin = start;            Endwin = end; }//if}//if}//for    return(m.size () = = Tlen);}intMain () {stringS"Acbbaca");stringT"ABA");intStart,end;BOOLresult = Minwindow (s,t,start,end);if(Result) {cout<<s.substr (start,end-start+1) <<endl; }//if    Else{cout<<"Not Found"<<endl; }//else    return 0;}

O (N) method:

Note that the above ideas are very complex. It uses a hash table, and a queue has a sorted map. In the interview process, the problem is often relatively short, the solution is usually around 50 lines of code. So it's important to say what you're thinking, and always keep in touch with the interviewer. Check if your method is not necessarily complicated and he/she can give you guidance. The worst thing is that you are trapped in a little bit and say nothing.

To illustrate this idea, I use a different example: S = "Acbbaca", T = "ABA". The main idea is to traverse s using two pointers to begin and end (window start and finish positions) and two arrays (Needtofind and Hasfound). Needtofind stores the total number of different characters in T, Hasfound stores the total number of different characters that have been encountered so far. We also use a count variable to store the total number of characters in T encountered so far (when hasfound[x] exceeds needtofind[x] without counting). When count is equal to the length of T, we find a valid window.

Each time we move the end pointer forward (point to an element x), we make hasfound[x] add one. If HASFOUND[X] is less than or equal to needtofind[x], Count plus one. Why? When the constraint is met (that is, Count equals T), we move the begin pointer to the right as far as possible, when the constraint is met.

How do we check if the constraints are met? Assuming that begin points to an element x, we check that hasfound[x] is greater than needtofind[x]. If so, we can make hasfound[x] minus one, moving the begin pointer forward without breaking the constraints. Conversely, if not, we immediately stop moving the begin pointer forward to prevent the constraint from being broken.

Finally, we check that the minimum window length is less than the current minimum window length. If not, the minimum window length is updated.

Essentially, the algorithm continues to maintain the constraint after it finds the first window that satisfies the constraint.


(1) S = "Acbbaca" T = "ABA"


(2) The first one to find the smallest window. We cannot move the begin pointer forward when hasfound[' a ']== needtofind[' a ']= = 2. Moving forward means breaking the constraint.


(3) A second window. The begin pointer still points to the first element, "a". Hasfound[' A '] (3) greater than needtofind[' a '] (2). We make hasfound[' a '] and move the begin pointer to the right.


(4) We skip element C because it is not in T. The begin pointer now points to element B. Hasfound[b] (2) greater than Needtofind[b] (1). We make hasfound[b] minus one, and move the begin pointer to the right.


(5) The Begin pointer now points to the next element, B. Hasfound[b] (1) equals needtofind[b] (1). We stopped at once, and this was the smallest window we had newly discovered.

The Begin pointer and end pointer are worst-case forward-moving up to N-Steps (n is the length of the string s), which adds up to 2N time, so the time complexity is O (n).

/*---------------------------------------------* Date: 2015-02-24* sjf0115* title: 22. The kid's window containing all the elements of T * Source: Algorithm Series * Blog:- ----------------------------------------------*/#include <iostream>#include <climits>#include <algorithm>using namespace STD;//Returns False if no valid window is found. Else returns//True and updates start and end with the//Starting and ending position of the minimum window.BOOLMinwindow (stringSstringTint&startwin,int&endwin) {intSlen = S.size ();intTlen = T.size ();if(Slen <=0|| Tlen <=0){return false; }//if    //Store the total number of different characters in T    intneedfind[ the] = {0}; for(inti =0; i < tlen;++i) {++needfind[t[i]]; }//for    //Stores the total number of different characters that have been encountered so far    inthasfound[ the] = {0};//Stores the total number of characters in t that have been encountered so far    intCount =0;intMinWin = Int_max;intEndele; for(intStart =0, end =0; end < Slen;++end) {Endele = S[end];//pruning useless characters (characters in T are useful characters)        if(Needfind[endele] = =0){Continue; }//if++hasfound[endele];if(Hasfound[endele] <= Needfind[endele])        {++count; }//if        //Find a valid window        if(count = = Tlen) {intBegele = S[start];//satisfy: Character is a useless character, Begele element Find more start pointer to move right             while(Needfind[begele] = =0|| Hasfound[begele] > Needfind[begele]) {if(Hasfound[begele] > Needfind[begele])                {--hasfound[begele]; }//if++start;            Begele = S[start]; }//while            //Update minimum window            intCurwin = End-start +1;if(Curwin < MinWin)                {MinWin = Curwin;                Startwin = start;            Endwin = end; }//if}//if}//while    return(count = = Tlen);}intMain () {stringS"Adobecodebanc");stringT"ABC");intStart,end;BOOLresult = Minwindow (s,t,start,end);if(Result) {cout<<s.substr (start,end-start+1) <<endl; }//if    Else{cout<<"Not Found"<<endl; }//else    return 0;}

Original link: Finding the Minimum Window in S which Contains all Elements from T

[Algorithm series 22] contains t all elements of the Kid's window

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.