LeetCode解析------30.串联所有单词的子串-哈希表

题目:

给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例 1:

输入: s = “barfoothefoobarman”, words = [“foo”,“bar”]
输出:[0,9]
解释:从索引 0 和 9 开始的子串分别是 “barfoo” 和 “foobar” 。 输出的顺序不重要, [9,0] 也是有效答案。

示例 2:

输入: s = “wordgoodgoodgoodbestword”, words = [“word”,“good”,“best”,“word”]
输出:[]

简单介绍:
题目:串联所有单词的子串
题目难度:困难
使用语言:JAVA。
这道题来自leetcode题库的哈希表标签。

解题思路:
首先看题、分析题意,我们可以明确1个关键点:
1.采用什么方式去比对子字符串和单词组会更加高效
既然,我们已经分析出来题目的关键任务了,下面我们就可以开始思考实现了。
我们采用算法与数据结构的思路来剖析一下这题,

数据结构:
要实现对数据的操作,我们要先明确存储数据的数据结构。
该题的数据结构的作用:
1.flagArray:保存单词组单词第i个的数值之和,作为特征。
2.bs:保存boolean结果,做数字压缩

算法:
既然明确了BitSet,int型数组作为解决该题的数据结构,我们就可以开始我们的算法分析了。
1.字符串或单词组为空的情况,返回空集
2.保存单词组单词的同一位置的数值,作为特征
3.对s进行截取,比对各部分单词是否符合特征
4.符合特征之后,再进行单词比对检验
5.bs中的true等于单词组的数目,则该单词符合条件

代码部分:

/*方案1*/
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

public class Solution{
    public List<Integer> findSubstring(String s, String[] words){
        List<Integer> res=new ArrayList<>();//保存结果
        if(s==null||s.length()==0||words==null||words.length==0){
            return res;
        }
        int wLen=words[0].length();//单个单词的长度
        int wTotalLen=wLen*words.length;//单词组的总长度
        int sLen=s.length();//字符串的长度
        int []flagArray=new int[wLen];//保存单词组单词的同一位置的数值,作为特征
        for(int i=0;i<wLen;i++){
            int flag=0;
            for(String word:words){
                flag+=word.charAt(i);//每个单词第i位的数值
            }
            flagArray[i]=flag;
        }

        BitSet bs=new BitSet(words.length);//方便保存boolean结果,做数字压缩
        for(int i=0;i<=sLen-wTotalLen;i++){
            int j;
            for(j=0;j<wLen;j++){
                int sumFlag=0;
                for(int k=0;k<words.length;k++){
                    sumFlag+=s.charAt(i+j+k*wLen);//以i为起点的子字符串,每个单词的第j位的数值
                }
                if(sumFlag!=flagArray[j]) break;//不符合特征
            }

            if(j==wLen){//判断是否匹配
                bs.clear();//使用前先清理上次保存的结果
                for(int k=0;k<words.length;k++){
                    String w=s.substring(i+k*wLen,i+(k+1)*wLen);//以i为起点的子字符串,第k个单词
                    int n;
                    for(n=0;n<words.length;n++){
                        if(!bs.get(n)&&words[n].equals(w)) {
                            bs.set(n);//设置第n位为1
                            break;
                        }
                    }
                    if (n==words.length) break;//单词组所有单词都不能于w对应
                }
                if (bs.cardinality()==words.length) res.add(i);

            }


        }
        return res;

    }
}

在这里插入图片描述

结语:
晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!

猜你喜欢

转载自blog.csdn.net/weixin_44337475/article/details/106104949