Find length of smallest window that contains all the characters of a string in another string

前端 未结 8 1501
不思量自难忘°
不思量自难忘° 2020-12-24 09:05

Recently i have been interviewed. I didn\'t do well cause i got stuck at the following question

suppose a sequence is given : A D C B D A B C D A C D and search seq

相关标签:
8条回答
  • 2020-12-24 09:51

    Here's my solution. It follows one of the pattern matching solutions. Please comment/correct me if I'm wrong.

    Given the input string as in the question A D C B D A B C D A C D. Let's first compute the indices where A occurs. Assuming a zero based index this should be [0,5,9].

    Now the pseudo code is as follows.

        Store the indices of A in a list say *orders*.// orders=[0,5,9]
        globalminStart, globalminEnd=0,localMinStart=0,localMinEnd=0;
        for (index: orders)
         {
           int i =index;
           Stack chars=new Stack();// to store the characters
          i=localminStart;
         while(i< length of input string)
           { 
               if(str.charAt(i)=='C') // we've already seen A, so we look for C
               st.push(str.charAt(i));
               i++;
               continue;
               else if(str.charAt(i)=='D' and st.peek()=='C')
               localminEnd=i; // we have a match! so assign value of i to len
               i+=1;
               break;
               else if(str.charAt(i)=='A' )// seen the next A
               break;
        }
         if (globalMinEnd-globalMinStart<localMinEnd-localMinStart)
         {
           globalMinEnd=localMinEnd;
           globalMinStart=localMinStart;
         }
       }
    
        return [globalMinstart,globalMinEnd]
        }
    

    P.S: this is pseudocode and a rough idea. Id be happy to correct it and understand if there's something wrong.

    AFAIC Time complexity -O(n). Space complexity O(n)

    0 讨论(0)
  • 2020-12-24 09:52

    Here is my O(m*n) algorithm in Java:

    class ShortestWindowAlgorithm {
    
        Multimap<Character, Integer> charToNeedleIdx; // Character -> indexes in needle, from rightmost to leftmost | Multimap is a class from Guava
        int[] prefixesIdx; // prefixesIdx[i] -- rightmost index in the hay window that contains the shortest found prefix of needle[0..i]
        int[] prefixesLengths; // prefixesLengths[i] -- shortest window containing needle[0..i]
    
        public int shortestWindow(String hay, String needle) {
            init(needle);
            for (int i = 0; i < hay.length(); i++) {
                for (int needleIdx : charToNeedleIdx.get(hay.charAt(i))) {
                    if (firstTimeAchievedPrefix(needleIdx) || foundShorterPrefix(needleIdx, i)) {
                        prefixesIdx[needleIdx] = i;
                        prefixesLengths[needleIdx] = getPrefixNewLength(needleIdx, i);
                        forgetOldPrefixes(needleIdx);
                    }
                }
            }
            return prefixesLengths[prefixesLengths.length - 1];
        }
    
        private void init(String needle) {
            charToNeedleIdx = ArrayListMultimap.create();
            prefixesIdx = new int[needle.length()];
            prefixesLengths = new int[needle.length()];
            for (int i = needle.length() - 1; i >= 0; i--) {
                charToNeedleIdx.put(needle.charAt(i), i);
                prefixesIdx[i] = -1;
                prefixesLengths[i] = -1;
            }
        }
    
        private boolean firstTimeAchievedPrefix(int needleIdx) {
            int shortestPrefixSoFar = prefixesLengths[needleIdx];
            return shortestPrefixSoFar == -1 && (needleIdx == 0 || prefixesLengths[needleIdx - 1] != -1);
        }
    
        private boolean foundShorterPrefix(int needleIdx, int hayIdx) {
            int shortestPrefixSoFar = prefixesLengths[needleIdx];
            int newLength = getPrefixNewLength(needleIdx, hayIdx);
            return newLength <= shortestPrefixSoFar;
        }
    
        private int getPrefixNewLength(int needleIdx, int hayIdx) {
            return needleIdx == 0 ? 1 : (prefixesLengths[needleIdx - 1] + (hayIdx - prefixesIdx[needleIdx - 1]));
        }
    
        private void forgetOldPrefixes(int needleIdx) {
            if (needleIdx > 0) {
                prefixesLengths[needleIdx - 1] = -1;
                prefixesIdx[needleIdx - 1] = -1;
            }
        }
    }
    

    It works on every input and also can handle repeated characters etc.

    Here are some examples:

    public class StackOverflow {
    
        public static void main(String[] args) {
            ShortestWindowAlgorithm algorithm = new ShortestWindowAlgorithm();
            System.out.println(algorithm.shortestWindow("AXCXXCAXCXAXCXCXAXAXCXCXDXDXDXAXCXDXAXAXCD", "AACD")); // 6
            System.out.println(algorithm.shortestWindow("ADCBDABCDACD", "ACD")); // 3
            System.out.println(algorithm.shortestWindow("ADCBDABCD", "ACD")); // 4
        }
    
    0 讨论(0)
提交回复
热议问题