串联所有单词的子串

.

在这里插入图片描述

题目链接

串联所有单词的子串

题目详情

在这里插入图片描述

题目解析

这里可以参考找到字符串中所有的字母异位词这道题,但是,一个是异位词,一个是异位串,将words中的字符串看出一个个的单词,就可以采用一样的思路来解决这个问题
需要注意的是:

  1. 这里不能采用数组来模拟容器,而只能使用向List<String,Integer>这样的链表来记录字符串的个数
  2. left和right一次性需要跳过的字节长度,是根据words中每个单词的长度来的
  3. 这道题我们依旧采用滑动窗口来解决问题,但是滑动窗口执行的次数却需要做出改变:
    在这里插入图片描述
    如图,滑动窗口的执行次数,也是根据words中每个单词的长度来的,且每次left与right开始遍历的位置也会相对发生偏移

算法原理

滑动窗口流程图

在这里插入图片描述

定义变量

双指针的初始值与滑动窗口的次数相同
每一次滑动窗口都需要不同的hash2,因此定义它的位置需要额外注意
创建变量count来记录有效字符串个数

进窗口

  1. 将right所在位置的字符串存到hash2中
  2. 维护有效字符串个数count

判断

判断窗口内字符串总长度是否超过words的所有字符串之和

出窗口

将left所在字符串移除hash2,在移除之前维护有效字符串个数count

更新结果

如果count与words的字符串个数相同,则满足条件,将当前窗口的left下标加入到返回链表中

我的答案

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        //创建返回值
        List<Integer> list = new ArrayList<Integer>();
        //创建hash1,存储words的字符串
        Map<String,Integer>hash1 = new HashMap<String,Integer>();
        for(String ss:words){
            hash1.put(ss,hash1.getOrDefault(ss,0)+1);
        }
        //滑动次数
        int wordLen = words[0].length(),size = words.length;
        for(int i = 0;i<wordLen;i++){
            //定义指针变量
             //创建hash2,存储窗口中的字符串
            Map<String,Integer>hash2 = new HashMap<String,Integer>();
            for(int left = i,right = i,count=0;right+wordLen<=s.length();right+=wordLen){
                //进窗口
                String in = s.substring(right,right+wordLen);
                hash2.put(in,hash2.getOrDefault(in,0)+1);
                //维护有效字符串
                if(hash2.get(in)<=hash1.getOrDefault(in,0))//hash1可能没有该值
                count++;
                //判断
                if(right-left+1>size*wordLen){
                    //出窗口
                    String out = s.substring(left,left+wordLen);
                    //维护有效字符串个数
                    if(hash2.get(out)<=hash1.getOrDefault(out,0))
                    count--;
                    hash2.put(out,hash2.get(out)-1);
                    left+=wordLen;
                }
                //更新结果
                if(count==words.length)
                list.add(left);
            }
        }
        return list;
    }
}
  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值