算法015:串联所有单词的子串

串联所有单词的子串. - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/substring-with-concatenation-of-all-words/

如果是第一次接触这个题目,接触滑动窗口的题目,那么这个题目则非常困难。但是经过我我们之前几个题的滑动窗口的磨炼,这个题只是在上一个题目的基础上变难了一些,细节变多了一些。

首先,题目的要求是返回符合要求的下标:

并且要注意的是,和右边的数组里面的元素相同才符合题意,如果只有一个foo或者一个bar,则不满足要求。

既然以3个字母为一组,那么我们就可以简化成这样:

把三个字符看成一个整体,left和right指针也是进行整体的加减。如此会出现一个问题,如果符合题目要求的字符,是从第二个,第三个字母开始的呢?

我们就循环几次,第一次把abb作为一个整体,第二次把bba作为一个整体,第三次把bar作为一个整体,并且只需要几次就可以全部覆盖到,这个次数和words里面的元素的长度有关。

在这个循环里面,就变成了跟上一个题目一样了,也是进窗口,维护count,出窗口,维护count

要注意的是,right和left的起始位置,跟上一层循环有关,right和left向右移动的长度,和words里面的元素的长度有关。

代码:

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> ret = new ArrayList<Integer>();

        Map<String, Integer> hash1 = new HashMap<String, Integer>();
        for(String str: words){
            hash1.put(str, hash1.getOrDefault(str,0) + 1);
        }
        int len = words[0].length();
        int m = words.length;
        for(int i = 0; i < len; i++){
            Map<String, Integer> hash2 = new HashMap<String, Integer>();
            for(int left = i, right = i, count = 0; right + len <= s.length(); right += len){
                String in = s.substring(right, right + len);
                hash2.put(in, hash2.getOrDefault(in, 0) + 1);
                if(hash2.get(in) <= hash1.getOrDefault(in, 0)){
                    count++;
                }
                if(right - left + 1 > len * m){
                    String out = s.substring(left, left + len);
                    if(hash2.get(out) <=  hash1.getOrDefault(out, 0)){
                        count--;
                    }
                    hash2.put(out, hash2.get(out) - 1);
                    left += len;
                }
                if(count == m){
                    ret.add(left);
                }
            }
        }
        return ret;
    }
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值