leetcode 30. 串联所有单词的子串(优质解法)

代码:

java 复制代码
class Solution {
    public static List<Integer> findSubstring(String s, String[] words) {
        List<Integer> integerList=new ArrayList<>();

        int length=words.length;    //words 数组中的字符串个数
        int size=words[0].length(); //words 数组中每个字符串的长度

        HashMap<String,Integer> hashMap1=new HashMap<>();   //存储 words 数组中字符串以及出现的个数


        //把 words 数组中字符串以及出现的个数保存到 hashMap1 中
        for(String str:words){
            hashMap1.put(str,hashMap1.getOrDefault(str,0)+1);
        }

        for(int i=0;i<size;i++){
            int count=0;    //记录当前子串中符合条件的字符串
            HashMap<String,Integer> hashMap2=new HashMap<>();   //存储讨论的子串中字符串以及出现的个数
            for(int left=i,right=i;right+size<=s.length();right+=size){
                //把 right 指针指向的数据入窗口
                String in=s.substring(right,right+size);
                hashMap2.put(in,hashMap2.getOrDefault(in,0)+1);

                //判断当前入窗口的字符串是否是符合条件的
                if(hashMap2.get(in)<=hashMap1.getOrDefault(in,0)){
                    count++;
                }

                //判断当前子串的长度是否过长,是否需要出窗口
                if(right-left+1>length*size){
                    String out=s.substring(left,left+size);
                    //判断出窗口的字符串是否是有效字符串
                    if(hashMap2.get(out)<=hashMap1.getOrDefault(out,0)){
                        count--;
                    }
                    hashMap2.put(out,hashMap2.get(out)-1);
                    left+=size;
                }

                //判断有效字符串个数是否符合条件
                if(count==length){
                    integerList.add(left);
                }
            }
        }
        return integerList;
    }
}

题解:

本题的含义表达得很明确,我们需要在字符串 s 中找到一个子串,子串由字符串数组 words 中的字符串以不同顺序组成

我们首先可以想到一个暴力解法,遍历出字符串 s 中的所有子串,找出完全由 words 中的字符串以不同顺序组成的子串。现在就涉及到一个问题,我们如何知道子串是完全由 words 中的字符串以不同顺序组成的

我们可以利用哈希表 hash1 和 hash2 存储 words 数组中和子串中字符串的相关信息,以字符串为 key ,个数为 value ,然后比对 hash1 和 hash2 中的内容,便知道当前子串是否是符合条件的

假设**输入:**s = "barfoothefoobar", words = ["foo","bar"]

首先我们可以获得的信息是,words 数组中的字符串个数 length = 2,每个字符串的大小 size = 3 ,由于我们要遍历所有的子串,所以让 L 和 R 指针指向下标为 0 的位置。我们将 words 数组中的相关信息保存到哈希表 hash1 中,foo-1,bar-1,用变量 count 记录子串中有效字符串的个数

因为符合要求的子串是由 words 数组中的字符串按不同顺序组成的,而 words 数组中的字符串是 3 个字符为一个整体,所以我们在寻找子串的时候也以 3 个字符为一个整体,R 指针指向当前位置,通过 s.substring(right,right+size) 取出字符串 bar,将 bar - 1 保存到 hash2 中,由于在hash1 中 bar-1,只要子串中的字符个数小于等于 wors 数组中对应字符的个数,就代表该字符是有效字符,所以 bar 是有效字符,此时 count++,count=1

b a r f o o t h e f o o b a r

L

R

录入字符串 bar 的信息以后,R 指针向右移动 size 位,录入下一个字符串 foo,将 foo- 1 保存到 hash2 中,由于在hash1 中 foo-1,,所以 foo 是有效字符,此时 count++,count=2,因为此时子串为 barfoo 长度为 6 == size*length ,并且 count == 2 == length,所以该子串是符合要求的,我们就直接记录 L 指针指向的下标 0

b a r f o o t h e f o o b a r

L

R

当 R 指针再向右移 size 位以后,子串为 barfoothe,大小为 9 > size * length ,字符数都比 words 数组中的字符数多了,肯定不符合要求,代表以 L 指针为首的子串已经讨论完毕,让 L 指针向右移动 size 位,讨论下一组字符串

b a r f o o t h e f o o b a r

L

R

L 指针之前指向的是字符串 bar ,bar 在 hash2 中的个数为 1,小于等于在 hash1 中的个数,所以是有效字符串,因此在将 L 指针移动前,我们需要修改 hash2 中的 bar - 0,count = 1,

此时子串的长度符合要求,但是有效字符串个数 count < length,所以该子串不符合要求,让 R 指针向右移动 size 位

b a r f o o t h e f o o b a r

L

R

之后循环上述操作即可

有细心的小伙伴会发现,上面的流程没有讨论完所有的子串,我们还需要以如下的两种情况,继续上述的操作,也就是在上述的循环操作要执行 size 次

b a r f o o t h e f o o b a r

L

R

b a r f o o t h e f o o b a r

L

R

相关推荐
m0_5719575828 分钟前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
pianmian13 小时前
python数据结构基础(7)
数据结构·算法
考试宝4 小时前
国家宠物美容师职业技能等级评价(高级)理论考试题
经验分享·笔记·职场和发展·学习方法·业界资讯·宠物
好奇龙猫5 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
sp_fyf_20245 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
香菜大丸6 小时前
链表的归并排序
数据结构·算法·链表
jrrz08286 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time6 小时前
golang学习2
算法
面试鸭6 小时前
离谱!买个人信息买到网安公司头上???
java·开发语言·职场和发展
南宫生7 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法