[LintCode] 最小子串覆盖 Java

Posted BrookLearnData

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LintCode] 最小子串覆盖 Java相关的知识,希望对你有一定的参考价值。

题目:

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

 注意事项

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

说明

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

——不需要。

样例

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

要求时间复杂度为O(n)

分析:采用哈希的思想,记录字母出现次数。
大小写字母的ASCII码不大于256,这样array[‘A‘]=3指A出现3次,array[‘B‘]=1指B出现了一次,以此类推,不能用常规意义上的定义array[0]=3表示A出现3次,这样就多了一层映射!故而数组的长度设置为256即可存放所有的字母。
首先预处理target,用256大小的整数数组tHash存储里面每个char出现的个数;
然后给定两个指标beg和end,一个移动start,也用一个256长的整数数组sHash记录从beg到end的这段字符串里面每个char出现的个数。如果sHash大于等于tHash,也就是说sHash里的每一位大于等于tHash里相应位置的值,找到当前start位置,为符合要求子串的起点,记录当前beg和end的长度,如果比已经记录的小,那么我们就选这个位最小窗口。记录beg和end。然后让start往前走一位。寻找下一个子串。

代码:

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(String source , String target) {
        // write your code here
        // write your code here
        int[] srcHash = new int[255];
        //记录目标字符串每个字母出现次数
        for(int i=0;i<target.length();i++){
            srcHash[target.charAt(i)]++;
        }

        int start =0,i=0;
        int[] destHash = new int[255];      //记录串口内每个字母出现的次数
        int found = 0;
        int begin = -1,end = source.length(),minLength  = source.length();
        for(start = i=0;i<source.length();i++){
            destHash[source.charAt(i)]++;       //没来一个字符给他出现次数加1
            //如果加1后,这个字符的数量不超过目标串中该字符数量,则找到了一个匹配字符
            if(destHash[source.charAt(i)] <= srcHash[source.charAt(i)]) found++;
            // 如果找到的匹配字符数等于目标串长度,说明找到了一个符合要求的子串
            if(found == target.length()){
                // 将开头没用的都跳过,没用是指该字符出现次数超过了目标串中出现的次数,并把它们出现次数都减1
                while(start < i && destHash[source.charAt(start)] > srcHash[source.charAt(start)]){
                    destHash[source.charAt(start)]--;
                    start++;
                }
                // 这时候start指向该子串开头的字母,判断该子串长度
                if(i - start < minLength){
                    minLength = i - start;
                    begin = start;
                    end = i;
                }
                // 把开头的这个匹配字符跳过,并将匹配字符数减1
                destHash[source.charAt(start)]--;
                found--;
                // 子串起始位置加1,我们开始看下一个子串了
                start++;
            }
        }
        return begin == -1 ? "" : source.substring(begin,end + 1);
    }
}

 

 

 

 




以上是关于[LintCode] 最小子串覆盖 Java的主要内容,如果未能解决你的问题,请参考以下文章

最大子串和问题最小子串覆盖问题

最小子串覆盖 · Minimum Window Substring

Leetcode53.最大子串和(简单)76.最小子串覆盖(困难)3. 最长子串不重复问题(中等)

Leetcode53.最大子串和(简单)76.最小子串覆盖(困难)3. 最长子串不重复问题(中等)

Leetcode53.最大子串和(简单)76.最小子串覆盖(困难)3. 最长子串不重复问题(中等)

Leetcode53.最大子串和(简单)76.最小子串覆盖(困难)3. 最长子串不重复问题(中等)