30. 与所有单词相关联的字串、java实现

题目描述:

给定一个字符串 s 和一些长度相同的单词 words。在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例 1:
输入:
 s = "barfoothefoobarman",
 words = ["foo","bar"]
输出: 
  [0,9]

解释: 从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。

示例 2:
输入:
 s = "wordgoodstudentgoodword",
 words = ["word","student"]

输出:
 []

滑动窗口法:

    // 参考博客:
    // http://www.cnblogs.com/migoo/p/9454684.html
    // 用了滑动窗口的方法
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> result = new ArrayList<Integer>();
        // 如果s,或者是words为空,那么也返回一个空的列表
        if (s.length() == 0 || s == null || words.length == 0 || words == null){
            return result;
        }
        int size = words[0].length(), length = words.length;

        // 把字符串数组中的的字符串全部插入HashMap中
        HashMap<String, Integer> map = generate(words);
        // 窗口的不同的起点,有size个不同的起点
        for (int i = 0; i < size; i++){
            HashMap<String, Integer> window= new HashMap<>();  // 一个滑动的窗口
            int left,right;
            left = right = i;
            while (right <= s.length() - size && left <= s.length() - length * size){
                String word = s.substring(right, right + size);
                incr(window, word);
                if (!map.containsKey(word)){
                    window.clear();
                    right += size;
                    left = right;
                    continue;
                }
                while (window.get(word) > map.get(word)){
                    String w = s.substring(left, left + size);
                    decr(window, w);
                    left += size;
                }
                right += size;
                if (right - left == size * length){
                    result.add(left);
                }
            }
        }
        return result;
    }
    private HashMap<String, Integer> generate(String[] strs){
        HashMap<String, Integer> map = new HashMap<>();
        for (String str : strs){
            incr(map, str);
        }
        return map;
    }

    private void incr(HashMap<String, Integer> map, String str) {
        map.put(str, map.getOrDefault(str,0) + 1);
    }
    private void decr(HashMap<String, Integer> map, String str) {
        Integer num = map.get(str);
        if (num <= 1){
            map.remove(str);
        }else {
            map.put(str, num - 1);
        }
    }

暴力法:

    // 参考博客
    // https://www.nowcoder.com/discuss/87526?type=0&order=0&pos=11&page=0
    // 暴力法
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> result = new ArrayList<Integer>();
        if (s.length() == 0 || s == null || words.length == 0 || words == null){
            return result;
        }
        int size = words[0].length();
        int length = words.length;
        // 截取字符串时,取左不取右,所以这里的for循环中i的最大值可以取等号
        for (int i = 0; i <= s.length() - size * length; i++){
            HashMap<String, Integer> map = new HashMap<>();
            for (String word : words){
                map.put(word, map.getOrDefault(word, 0) + 1);
            }
            if (check(s,i,map,size)){
                result.add(i);
            }
        }
        return result;
    }

    private boolean check(String s, int i, HashMap<String, Integer> map, int size) {
        if (map.size() == 0){
            return true;
        }
        if (i > s.length() || i + size > s.length()){
            return false;
        }
        String word = s.substring(i, i + size);
        if (!map.containsKey(word)){
            return false;
        }else {
            Integer num = map.get(word);
            if (num <= 1){
                map.remove(word);
            }else {
                map.put(word, num - 1);
            }

           return check(s, i + size, map, size);
        }
    }
posted @ 2018-08-14 23:41  DaleyZou  阅读(534)  评论(0编辑  收藏  举报