leetcode30.串联所有单词的子串——学习笔记

题目:力扣https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<String> baseList = Arrays.asList(words);//将字符出串数组转化为集合
        List<String> wordList;//提前声明,备用
        List<Integer> res = new ArrayList<>();//用于存答案的集合
        int len = words[0].length();//word的长度,题目规定了各个word都相等
        for(int cur=0;cur<=s.length()-len*words.length;cur++){
            //s.length()-len*words.length//当s.leng()的长度比word的总长度要小的时候即表示已经到尽头
            boolean flag = true;//记录匹配状态
            wordList = new ArrayList<>(baseList);//
            for(int i=0;i<words.length;i++){
                if(!flag){
                    continue;
                }
                flag = wordList.remove(s.substring(cur+(i*len) , cur+((i+1)*len)));
                //移除成功给返回true,移除失败返回false。即进行了比对,有避免了重复,妙哉妙哉
            }
            if(flag){//flag的值为true的时候表示匹配成功,记录下起初位置的下标
                res.add(cur);
            }
        }
        return res;
    }
}

 

思路:这一题我也是学习了别的大佬的思路,关键在于巧妙地使用remove(),用remove()一个方法同时做到判别与去重的两个作用。 

1.准备工作。将words数组转换成集合,方便后续操作;wordList是后续需要用到的临时集合,在此处先声明;res是用于存储最后答案的集合。因为题目规定,words中的每个字符串的长度是相等的,即可以用word[0]的长度代表所有words数组中字符串的长度,并将其存储在len变量中。

List<String> baseList = Arrays.asList(words);//将字符出串数组转化为集合
List<String> wordList;//提前声明,备用
List<Integer> res = new ArrayList<>();//用于存答案的集合
int len = words[0].length();//word的长度,题目规定了各个word都相等

2.cur是表示原字符串s当前的位置,当cur到达一定的位置即代表长度已经不够,不可能匹配成功了。(这个临界点是:s.length()-len*words.length)声明一个flag用于记录当前匹配状态的,将baseList赋值给wordList集合(因为后面需要对集合进行remove操作,因为不确保一次循环即可匹配成功,所以需要一个临时的集合来做baseList的替身,让wordList来做remove操作。这样就算第一次循环没有匹配成功,但仍然保证了baseList的完整性,在下一次循环中可以重新赋值给wordList,再一次进行匹配。)

for(int cur=0;cur<=s.length()-len*words.length;cur++){
//s.length()-len*words.length//当s.leng()的长度比word的总长度要小的时候即表示已经到尽头
    boolean flag = true;//记录匹配状态
    wordList = new ArrayList<>(baseList);//
    //....
}

3.i表示单词word的个数。if(!flag){...}表示如果,flag为false表示已经匹配失败了,则不需要进行下面进一步的匹配了,需要返回上一层改变原字符串s的起始位置;若flag为true则表示暂时匹配成功了,可以进一步的匹配。flag = wordList.remove(s.substring(cur+(i*len) , cur+((i+1)*len)));这一句是这份代码最精髓的一句代码,它的作用是让通过 原字符串s中特定位置的一段 与 单词word集合 的比对判断是否匹配成功。若删除成功表示匹配成功,会返回true值给flag同时把该单词去除,达到去重的目的,非常非常的巧妙。

for(int i=0;i<words.length;i++){
    if(!flag){
        continue;
    }
    flag = wordList.remove(s.substring(cur+(i*len) , cur+((i+1)*len)));
     //移除成功给返回true,移除失败返回false。即进行了比对,有避免了重复,妙哉妙哉
}

8.剩下只需要根据flag的判断上面是否匹配成功,若成功则将原字符串s的起始位置cur记录再res集合中,若不成功则移动原字符串s的起始位置cur,进行新一轮的匹配。

if(flag){//flag的值为true的时候表示匹配成功,记录下起初位置的下标
    res.add(cur);
}

9.最后的最后,只需要返回装着答案的集合res即可。

return res;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hokachi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值