LintCode:M-最小子串覆盖

来源:互联网 发布:手机源码是什么 编辑:程序博客网 时间:2024/06/10 20:00

给定一个字符串source和一个目标字符串target,在字符串source找到包括所有目标字符串字母的子串。

 注意事项

如果在source没有这样的子串,返回"",如果有多个这样的子串,返回起始位置最小的子串。

说明

在答案的子串中的字母在目标字符串中是否需要具有相同的顺序?

——不需要。

样例

给出source = "ADOBECODEBANC"target = "ABC" 满足要求的解  "BANC"


分析

利用字符串的特性,开辟两个128长度的字符空间来直接定位不同的字符,记录出现的次数

如果要节约空间的话,可以用开辟两个Hash

TC = O(n)


public class Solution {    /**     * @param source: A string     * @param target: A string     * @return: A string denote the minimum window     *          Return "" if there is no such a string     */    //数组方式    public String minWindow_array(String source, String target) {        int ns = source.length();        int nt = target.length();        int[] countSor = new int[128];        int[] countTar = new int[128];        char[] sors = source.toCharArray();        char[] tars = target.toCharArray();                for(int i=0; i<nt; i++){            countTar[tars[i]]+=1;        }                int count=0;        int start=0, begin=-1, end=0, minLen=Integer.MAX_VALUE;        for(int i=0; i<ns; i++){            countSor[sors[i]]+=1;                        if(countSor[sors[i]]<=countTar[sors[i]]){                count++;            }                        if(count==tars.length){                //相当于把之前的出栈                //找到sor中国前面最开始的Tar中的字符                while(start<i && countSor[sors[start]]>countTar[sors[start]]){                    countSor[sors[start++]]--;                }                                if(i-start+1<minLen){                    minLen = i-start+1;                    begin = start;                    end = i;                }                                //找到了一个                //现在去掉一个,继续往后找下一个符合要求的                countSor[sors[start++]]--;                count--;            }        }                if(begin!=-1)            return source.substring(begin, end+1);        else            return "";    }}