LintCode 最小子串覆盖 Hash表

最近秋招之路告一段落,玩了好几天。。。

今天咸鱼般的水了一题,花了些时间= =

题目:原题地址

 

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

 注意事项

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

说明

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

——不需要。

样例

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

挑战 

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

 

解题思路:

用两个map,sMap表示原串中,需要比较的字符出现的次数   tMap表示目标串中,需要比较的字符出现的次数

当tMap里的数据都小于等于sMap时,即找到了结果。

而难点就是怎样在O(n)的复杂度内完成要求,并且找到最小的结果

 

时间复杂度要求O(n),可是两个字符串是必须要遍历的,那么就需要在遍历字符串的过程中完成操作,那么我们可以在遍历的过程中,找出一次次满足结果的解,

最后取最小的就行了,这样便能控制在O(n)的时间内

 

详细注释和代码如下:

public String minWindow(String source, String target) {
        int len1 = source.length();// 原串的长度
        int len2 = target.length();// 目标串长度

        if (len1 < len2)//条件不满足,直接返回""
            return "";

        String result = "";//用于记录结果
        int minLen = len1 + 1;//用于记录最小长度

        Map<Character, Integer> sMap = new HashMap<Character, Integer>();//用于原串的哈希表
        Map<Character, Integer> tMap = new HashMap<Character, Integer>();//用于目标串的哈希表

        for (int i = 0; i < len2; i++) {//将目标串中,出现字符的个数放入tMap
            if (tMap.containsKey(target.charAt(i))) {
                tMap.put(target.charAt(i), tMap.get(target.charAt(i)) + 1);
            } else {
                tMap.put(target.charAt(i), 1);
            }
        }

        int count = 0;//用于记录放入sMap的个数,目的是找到第一个成立的result。和以后出现的result
        for (int i = 0; i < len1; i++) {
            int Len = 0;
            //依次比较原串与目标串。同步两个Map里的数据。用count来找出现结果的时候(count==len2)
            if (tMap.containsKey(source.charAt(i))) {
                if (sMap.containsKey(source.charAt(i))) {
                    if (sMap.get(source.charAt(i)) < tMap.get(source.charAt(i))) {
                        count++;
                    }
                    sMap.put(source.charAt(i), sMap.get(source.charAt(i)) + 1);
                } else {
                    sMap.put(source.charAt(i), 1);
                    count++;
                }
            }

            if (count == len2) {//此时出现了结果
                char c = source.charAt(Len);
                //找到结果的起始位置
                while (!sMap.containsKey(c) || sMap.get(c) > tMap.get(c)) {
                    if (sMap.containsKey(c) && sMap.get(c) > tMap.get(c))
                        sMap.put(c, sMap.get(c) - 1);
                    c = source.charAt(++Len);//len的长度,即为此时result的开始位置
                }

                //得到最终结果
                if (i - Len + 1 < minLen) {
                    result = source.substring(Len, i + 1);
                    minLen = i - Len + 1;
                }
            }
        }

        return result;
    }

 

最后附上一张AC图~

 

posted @ 2017-09-18 10:26  夏天的冬天  阅读(198)  评论(0编辑  收藏  举报