查找最小窗口子字符串-leetcode-解决方案不起作用

时间:2019-09-21 06:16:28

标签: java string algorithm

问题:https://leetcode.com/problems/minimum-window-substring/

给出一个字符串S和一个字符串T,在S中找到最小窗口,其中将包含复杂度为O(n)的T中的所有字符。

示例:

输入:S =“ ADOBECODEBANC”,T =“ ABC” 输出:“ BANC”

我尝试使用滑动窗口技术来提出解决方案,但是我被困在这里。可以帮忙吗?

    package com.tryPrep.Strings;

import java.util.HashMap;

public class MinWindowSubstring {

    static String minWinSubStr(String s, String t){

        HashMap<Character, Integer> tabl = new HashMap<>();

        for(char c: t.toCharArray()){
            int charCount=0;
            if(tabl.containsKey(c))
              charCount = tabl.get(c);
            tabl.put(c, charCount+1);
        }

        int begin =0, end =0, counter=tabl.size();

        String ans="";
        int max=s.length();
        while(end < s.length()) {

            char endChar = s.charAt(end);
            if (tabl.containsKey(endChar)) {
                int charCount = tabl.get(endChar);
                if (charCount > 0) {
                    counter--;
                    tabl.put(endChar, charCount - 1);
                }
            }
            end++;

            while (counter == 0) {

                if (max > end - begin) {
                    ans = s.substring(begin, end - begin);
                    max = ans.length();
                }

                char beginChar = s.charAt(begin);
                if (tabl.containsKey(beginChar)) {
                    int charCount = tabl.get(beginChar);
                    if(charCount == 0) {
                        tabl.put(beginChar, charCount + 1);
                        counter++;
                    }
                }

                begin++;
            }
        }

        return ans;
    }


    public static void main(String[] args) {

        String s = "ADOBECODEBANC";
        String t = "ABC";

        System.out.println("minWinSubStr M1 : " + minWinSubStr(s, t));

    }
}

输出:

minWinSubStr M1 : ADOBEC

我看到当end到达字符串长度时循环变得满意,但此处的计数器仍不为0。您能否指出我要解除封锁的问题是什么?

1 个答案:

答案 0 :(得分:1)

问题是当您删除A(在索引0)后增加计数器的数量时。您开始寻找另一个A来弥补这一损失。

ADOBECODEBANC
 ^        ^
begin    end
  

这样做时,在不知不觉中您的代码没有考虑到B(在索引9),并且结束指针到达了A(在索引10)。

此后,当开始指针到达B(在索引4处)并且您增加了计数器时,结束指针便找不到其他B。

ADOBECODEBANC
    ^     ^
  begin  end

因此,您得到的答案为 ADOBEC

  

当末端指针找到任何必须考虑的字符时,您可以采取的纠正措施,删除该字符的第一个索引并添加最近遇到的那个。

     

一旦这样做,您就可以轻松地在开始指针遇到该字符时忽略该字符,因为该字符的频率不会受到影响。

     

这是有效的,因为我们要从头开始缩小窗口,而不是从头开始缩小窗口。

对于您而言,您可以在每次结束指针遇到 tabl 中的任何字符时减少计数器。

现在,当开始指针遇到任何值为负的字符时,不要增加计数器的值,而只需对值加1。

此外,您应该从头到尾打印值。
s.substring(begin, end)

假设在begin = 8和end = 10的情况下
s.substring(8, 10), not s.substring(8, 2)

static String minWinSubStr(String s, String t) {
    System.out.println(s);
    System.out.println(t);

    HashMap<Character, Integer> tabl = new HashMap<>();

    for (char c : t.toCharArray()) {
        int charCount = 0;
        if (tabl.containsKey(c))
            charCount = tabl.get(c);
        tabl.put(c, charCount + 1);
    }

    int begin = 0, end = 0, counter = tabl.size();

    String ans = "";
    int max = s.length();
    while (end < s.length()) {
        char endChar = s.charAt(end);
        if (tabl.containsKey(endChar)) {
            int charCount = tabl.get(endChar);
            if (charCount > 0) {
                counter--;
            }
            tabl.put(endChar, charCount - 1);
        }
        end++;

        while (counter == 0) {
            if (max > end - begin) {
                ans = s.substring(begin, end);
                max = ans.length();
            }

            char beginChar = s.charAt(begin);
            if (tabl.containsKey(beginChar)) {
                int charCount = tabl.get(beginChar);
                if(charCount < 0) {
                    tabl.put(beginChar, charCount + 1);
                }
                else if (charCount == 0) {
                    tabl.put(beginChar, charCount + 1);
                    counter++;
                }
            }

            begin++;
        }
    }

    return ans;
}

突出显示了我已更改的部分。

  

注意:此代码仅解决您的用例,并且不应在所有测试用例上提供AC

相关问题