串联所有单词的子串(双指针算法)

hello,大家好,我是魔笑,今天给大家带来的是lettocde的30题。

今天唠叨一下自己写博客的目的:

我写博客,也是在记录自己学习的每一道题,和自己学习的东西,为什么要写博客,我的想法是,虽然经常学习,但是,如果不记下来,过段时间,就遗忘了。我之前也学了很多东西,但是过段时间有点记不清了,就感觉和没学差不多。学习就没什么动力了,如果我记下来,看博客越来越多,感觉这都是自己的知识,学习也就有了动力。

我希望小伙伴们,也都把自己学的东西记录下来,也不一定要写博客,但一定要归纳总结。

话不多说,看题:

题目:

给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words 中单词串联的顺序。

示例 1:

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

我解这道题,的思路,是双指针,这类题,我觉的用双指针非常好做

思路:

1,首先我们用map1集合存储words里面的字符串,key是字符串,values是该字符串的个数,因为words里面的单词,可能是重复的,再用一个map2集合存储,遍历的字符串,这样两个集合做对比就能判断遍历的字符串是否符合。

2,首先我们将start指针,指向b,下标为0,题目说words中的字符串相同,都为“L”长度,我们将从下标0开始,移动L个长度,end就指向了f下标为3,截取下标start到end的字符,判断map集合是否包含,并且map2集合里的个数并且加上这个是否大于map集合的个数,如果满足,将字符串加入map2,。

3,继续将end向后移L长度,直到连续截取的子串个数,等于words单词的个数,满足条件。将初始下标加入集合中去。

 

4,将start指针后移,重复上述过程。

4,将map1指针后移,重复上面的过程直到,start指针指向的下标,到字符串末尾,大于words里单词的总长度,再往下移动,就截取不到满足条件的字符串的个数了。

 代码:

代码一,是我的初版,代码,看着就很不舒服,所以我们再写完之后得优化,我们要精益求精,做一个优雅得码农,看如下代码,没有注释,就很难理解,而且if,else太多,不便于理解。

 public static List<Integer> findSubstring(String s, String[] words) {
        List<Integer> result = new LinkedList<>();
        int length = s.length();
        int wordChildLength = words[0].length();
        int wordLength = words.length;
        int totals = wordChildLength * wordLength;
        if (totals > length) {
            return result;
        }
        HashMap map = new HashMap();
        for (String str : words) {
            int count = (Integer) map.getOrDefault(str, 0);
            map.put(str, count + 1);
        }
        int end = -1;
        HashMap next = new HashMap();
        for (int start = 0; start < length; start++) {
            String str = "";
            while (end + 1 < length) {
                str += s.charAt(end + 1);
                if (str.length() == wordChildLength) {
                    if (map.get(str) != null) {
                        int i = (Integer) map.get(str);
                        int j = (Integer) next.getOrDefault(str, 0);
                        if (j < i) {
                            next.put(str, j + 1);
                        } else {
                            break;
                        }
                    } else {
                        break;
                    }
                    str = "";
                }
                if (end + 1 - start + 1 == totals) {
                    result.add(start);
                    break;
                }
                ++end;
            }
            end = start;
            next.clear();
        }
        return result;
    }

 代码二,改良版本,着看着就很舒服么。

    public static List<Integer> findSubstring1(String s, String[] words) {
        List<Integer> result = new LinkedList<>();
        int length = s.length();
        //单词长度
        int wordLength = words[0].length();
        //words中单词的个数
        int wordsCount = words.length;
        //words里单词的总长度
        int wordsTotal= wordLength * wordsCount;
        if (wordsTotal > length) {
            return result;
        }
        //将words中单词放入map1中
        HashMap map1 = new HashMap();
        for (String str : words) {
            int count = (Integer) map1.getOrDefault(str, 0);
            map1.put(str, count + 1);
        }
        //遍历字符串s
        for (int start = 0; start <= length - wordsTotal; start++) {
            HashMap map2 = new HashMap();
            //用于计算,符合条件字符串的个数
            int count=0;
            while (true) {
                //截取start指针到end指针的字符串,end=start+wordLength*count + wordLength
                String str = s.substring(start+wordLength*count, start+wordLength*count + wordLength);
                if (!map1.containsKey(str)) {
                    break;
                }
                int i = (Integer) map1.get(str);
                int j = (Integer) map2.getOrDefault(str, 0);
                if (j+1 > i) {
                    break;
                }
                map2.put(str, j + 1);
                count++;
                //将count等于words单词的个数,说明符合条条件,将初始下标加入结果集
                if (count==wordsCount) {
                    result.add(start);
                    break;
                }
            }
        }
        return result;
    }

如果对你有帮助,给个赞呗,谢谢

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值