在含有字符串2和3字符串的所有字符无字符串1最小化窗口 [英] Minimum window in String 1 containing all characters from String 2 and no character from String 3

查看:161
本文介绍了在含有字符串2和3字符串的所有字符无字符串1最小化窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好了,这是一个面试问题。而且没有它不是这个问题的副本。

由于3串 - STR1 STR2 STR3

  STR1 =spqrstrupvqw
STR2赛车=SPRT
STR3 =Q
 

我们已经找到的最小窗口 STR1 ,其中包含 STR2 所有字符的任意顺序,但没有从 STR3字符。在这种情况下,答案是:strup

我来到了这个code:

 静态字符串minimumWindow(字符串STR1,字符串STR2,字符串STR3){

        Window类实现可比<窗​​口> {
            INT开始;
            打算;

            公共窗口(INT开始,诠释完){
                this.start =启动;
                this.end =结束;
            }

            公众诠释getEnd(){
                返回结束;
            }

            公众诠释getStart(){
                返回启动;
            }

            公众诠释的compareTo(窗口O){
                INT thisDiff =结束 - 启动;
                INT thatDiff = o.end  -  o.start;

                返回Integer.compare(thisDiff,thatDiff);
            }

            @覆盖
            公共字符串的toString(){
                返回[+启动+:+端+];
            }
        }

        //创建字符集为包含()检查

        设置<性格> str2Chars =新的HashSet<>();
        对于(CHAR CH:str2.toCharArray()){
            str2Chars.add(CH);
        }

        设置<性格> str3Chars =新的HashSet<>();
        对于(CHAR CH:str3.toCharArray()){
            str3Chars.add(CH);
        }

        //这将存储不包含字符的所有有效窗口
        //从STR3。
        设置<窗​​口>设置=新TreeSet的<>();

        INT开始= -1;

        //这个循环获取每一对指标,使得从子
        // [开始,结束),每个窗口不包含STR3任何字符
        的for(int i = 0; I< str1.length();我++){
            如果(str3Chars.contains(str1.charAt(ⅰ))){
                 set.add(新窗口(开始,我));
                 开始= I + 1;
            }
        }

        INT的minLength = Integer.MAX_VALUE的;
        字符串minString =;

        //遍历窗口查找包含所有的最小长度的字符串
        从STR2 //字符
        对于(窗窗:集){
            如果((window.getEnd() -  1  -  window.getStart())≤; str2.length()){
                继续;
            }

            对于(INT I = window.getStart(); I< window.getEnd();我++){
                如果(str2Chars.contains(str1.charAt(ⅰ))){
                      //在这个窗口就是与str2中得到第一个字符
                      //开始从最终迭代来获得最后一个字符
                      // [开始,结束)子将是最小长度
                      //串在此窗口
                     对于(INT J = window.getEnd() -  1; J>我; j--){
                        如果(str2Chars.contains(str1.charAt(J))){
                            字符串s = str1.substring(I,J + 1);

                            设置<性格> sChars =新的HashSet<>();
                            对于(CHAR CH:s.toCharArray()){
                                sChars.add(CH);
                            }

                            //如果子包含了所有的字符STR2,
                            //那么只有它是有效的窗口。
                            如果(sChars.containsAll(str2Chars)){
                                INT的len = sChars.size();
                                如果(LEN<的minLength){
                                    的minLength = LEN;
                                    minString =秒;
                                }
                            }
                        }
                    }
                }
            }
        }

    //有些时候,一些尾随和前导字符是个案
    //在中间重复的地方。我们不需要它们包括在
    //的minLength。
    //在给定的例子,实际的字符串会来的 - rstrup,但我们
    //删除第一个R安全。
        StringBuilder的strBuilder =新的StringBuilder(minString);

        而(strBuilder.length()→1&安培;&安培; strBuilder.substring(1)。载(+ strBuilder.charAt(0))){
            strBuilder.deleteCharAt(0);
        }

        而(strBuilder.length()→1&安培;&安培; strBuilder.substring(0,strBuilder.length() -  1)。载(+ strBuilder.charAt(strBuilder.length() -  1))){
            strBuilder.deleteCharAt(strBuilder.length() -  1);
        }

        返回strBuilder.toString();
    }
 

不过,这并不对所有的测试用例工作。它的工作在这个问题中给出的例子。但是,当我提出的code,它没有为2的测试用例。不,我不知道的测试用例,它失败了。

即使在尝试不同的采样输入,我无法找到它失败测试用例。有人可以来看看,什么是错的code?我真的AP preciate,如果有人可以提供一个更好的算法(只是在伪code)。我知道这是真的不是最优化的解决方案,但。

解决方案

  STR1 =spqrstrupvqw
STR2赛车=SPRT
STR3 =Q
 

我们正在寻找最小的子串,从 STR1 包含所有 STR2 字符的(假设订购)并没有从 STR3字符 ..

  I = 1 .. str1.length
光标= 1 .. str2.length
 

该解决方案必须在窗体上的:

  str2.first X X .. X X str2.last
 

因此​​,为了检查该子字符串,我们使用游标了 STR2 ,但我们也有避免的约束STR3 字符,因此我们有:

 如果str3.contain(STR1 [I])
    光标= 1
其他
    如果str1 [我] == STR2 [光标]
        光标++
 

目标检查是:

 如果光标> str2.length
    回报的解决方案
其他
    如果我> = str1.length
        返回未找到
 

和优化,您可以跳到下一个先行是:

 前瞻= {STR2 [光标]或{X |的X STR3}}
 


如果 STR2 没有下令

  I = 1 .. str1.length
查找= {X |的X STR2}
 

该解决方案必须在窗体上的:

  STR2 [X] X X .. X X STR2 [X]
 

因此​​,为了检查该子字符串,我们使用核对表 STR2 ,但我们也有避免的约束STR3 字符,因此我们有:

 如果str3.contain(STR1 [I])
    查找= {X |的X STR2}
其他
    如果lookup.contain(STR1 [I])
        lookup.remove(STR1 [I])
 

目标检查是:

 如果查找是空的
    回报的解决方案
其他
    如果我> = str1.length
        返回未找到
 

和优化,您可以跳到下一个先行是:

 前瞻= {{X |的X查找}或{X |的X STR3}}
 


code

 类解决方案
{
    私有静态的ArrayList<性格> getCharList(字符串str)
    {
        返回Arrays.asList(str.getCharArray());
    }

    私有静态无效的FindFirst(一个字符串,字符串B,串c)
    {
        INT光标= 0;
        INT开始= -1;
        INT端= -1;

        ArrayList的<性格>流= getCharList(一);
        ArrayList的<性格>查找= getCharList(B);
        ArrayList的<性格>避免= getCharList(C);

        对于(字符ch:流)
        {
            如果(avoid.contains(CH))
            {
                查找= getCharList(B);
                开始= -1;
                结束= -1;
            }
            其他
            {
                如果(lookup.contains(CH))
                {
                    lookup.remove(CH)

                    如果(开始== -1)启动=光标;

                    结束=光标;
                }
            }

            如果(lookup.isEmpty())
                打破;

            光标++;
        }

        如果(lookup.isEmpty())
        {
            的System.out.println(发现了在(+启动+:+端+));
        }
        其他
        {
            的System.out.println(找不到);
        }
    }
}
 

Ok, this is an interview question. And no it's not a duplicate of this question.

Given 3 strings - str1, str2, str3:

str1 = "spqrstrupvqw"
str2 = "sprt"
str3 = "q"

We've to find the minimum window in str1, which contains all characters from str2 in any order, but no character from str3. In this case the answer would be: "strup".

I've come up with this code:

static String minimumWindow(String str1, String str2, String str3) {

        class Window implements Comparable<Window> {
            int start;
            int end;

            public Window(int start, int end) {
                this.start = start;
                this.end = end;
            }

            public int getEnd() {
                return end;
            }

            public int getStart() {
                return start;
            }

            public int compareTo(Window o) {
                int thisDiff = end - start;
                int thatDiff = o.end - o.start;

                return Integer.compare(thisDiff, thatDiff);
            }

            @Override
            public String toString() {
                return "[" + start + " : " + end + "]";
            }
        }

        // Create Sets of characters for "contains()" check

        Set<Character> str2Chars = new HashSet<>();
        for (char ch: str2.toCharArray()) {
            str2Chars.add(ch);
        }

        Set<Character> str3Chars = new HashSet<>();
        for (char ch: str3.toCharArray()) {
            str3Chars.add(ch);
        }

        // This will store all valid window which doesn't contain characters
        // from str3.
        Set<Window> set = new TreeSet<>();

        int begin = -1;

        // This loops gets each pair of index, such that substring from 
        // [start, end) in each window doesn't contain any characters from str3
        for (int i = 0; i < str1.length(); i++) {
            if (str3Chars.contains(str1.charAt(i))) {
                 set.add(new Window(begin, i));
                 begin = i + 1;
            }
        }

        int minLength = Integer.MAX_VALUE;
        String minString = "";

        // Iterate over the windows to find minimum length string containing all
        // characters from str2
        for (Window window: set) {
            if ((window.getEnd() - 1 - window.getStart()) < str2.length()) {
                continue;
            }

            for (int i = window.getStart(); i < window.getEnd(); i++) {
                if (str2Chars.contains(str1.charAt(i))) {
                      // Got first character in this window that is in str2
                      // Start iterating from end to get last character
                      // [start, end) substring will be the minimum length
                      // string in this window
                     for (int j = window.getEnd() - 1; j > i; j--) {
                        if (str2Chars.contains(str1.charAt(j))) {
                            String s = str1.substring(i, j + 1);

                            Set<Character> sChars = new HashSet<>();
                            for (char ch: s.toCharArray()) {
                                sChars.add(ch);
                            }

                            // If this substring contains all characters from str2, 
                            // then only it is valid window.
                            if (sChars.containsAll(str2Chars)) {
                                int len = sChars.size();
                                if (len < minLength) {
                                    minLength = len;
                                    minString = s;
                                }
                            }
                        }
                    }
                }
            }
        }

    // There are cases when some trailing and leading characters are
    // repeated somewhere in the middle. We don't need to include them in the
    // minLength. 
    // In the given example, the actual string would come as - "rstrup", but we
    // remove the first "r" safely.
        StringBuilder strBuilder = new StringBuilder(minString);

        while (strBuilder.length() > 1 && strBuilder.substring(1).contains("" + strBuilder.charAt(0))) {
            strBuilder.deleteCharAt(0);
        }

        while (strBuilder.length() > 1 && strBuilder.substring(0, strBuilder.length() - 1).contains("" + strBuilder.charAt(strBuilder.length() - 1))) {
            strBuilder.deleteCharAt(strBuilder.length() - 1);
        }

        return strBuilder.toString();
    }

But it doesn't work for all the test cases. It does work for the example given in this question. But when I submitted the code, it failed for 2 test cases. No I don't know the test cases for which it failed.

Even after trying various sample inputs, I couldn't find a test case for which it fails. Can someone take a look as to what is wrong with the code? I would really appreciate if someone can give a better algorithm (Just in pseudo-code). I know this is really not the optimized solution though.

解决方案

str1 = "spqrstrupvqw"
str2 = "sprt"
str3 = "q"

We're looking for the minimum sub-string from str1 that contain all str2 characters (assume ordered) and no characters from str3 ..

i = 1 .. str1.length
cursor = 1 .. str2.length

The solution must be on the form:

str2.first X X .. X X str2.last

So to check for that sub-string we use a cursor over str2, but we also have the constraint of avoiding str3 characters, so we have:

if str3.contain(str1[i])
    cursor = 1
else
    if str1[i] == str2[cursor]
        cursor++

Goal check is:

if cursor > str2.length
    return solution
else
    if i >= str1.length
        return not-found

And for optimization, you can skip to the next look-ahead which is:

look-ahead = { str2[cursor] or { X | X in str3 }}


In case str2 is not ordered:

i = 1 .. str1.length
lookup = { X | X in str2 }

The solution must be on the form:

str2[x] X X .. X X str2[x]

So to check for that sub-string we use a check-list str2, but we also have the constraint of avoiding str3 characters, so we have:

if str3.contain(str1[i])
    lookup = { X | X in str2 }
else
    if lookup.contain(str1[i])
        lookup.remove(str1[i])

Goal check is:

if lookup is empty
    return solution
else
    if i >= str1.length
        return not-found

And for optimization, you can skip to the next look-ahead which is:

look-ahead = {{ X | X in lookup } or { X | X in str3 }}


Code

class Solution
{
    private static ArrayList<Character> getCharList (String str)
    {
        return Arrays.asList(str.getCharArray());
    }

    private static void findFirst (String a, String b, String c)
    {
        int cursor = 0;
        int start = -1;
        int end = -1;

        ArrayList<Character> stream = getCharList(a);
        ArrayList<Character> lookup = getCharList(b);
        ArrayList<Character> avoid = getCharList(c);

        for(Character ch : stream)
        {
            if (avoid.contains(ch))
            {
                lookup = getCharList(b);
                start = -1;
                end = -1;
            }
            else
            {
                if (lookup.contains(ch))
                {
                    lookup.remove(ch)

                    if (start == -1) start = cursor;

                    end = cursor;
                }
            }

            if (lookup.isEmpty())
                break;

            cursor++;
        }

        if (lookup.isEmpty())
        {
            System.out.println(" found at ("+start+":"+end+") ");
        }
        else
        {
            System.out.println(" not found ");
        }
    }
}

这篇关于在含有字符串2和3字符串的所有字符无字符串1最小化窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆