美文网首页
30. 串联所有单词的子串

30. 串联所有单词的子串

作者: Abeants | 来源:发表于2022-07-16 10:49 被阅读0次

给定一个字符串 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"]
输出:[]

示例 3:
输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]

提示:
1 <= s.length <= 104
s 由小写英文字母组成
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i] 由小写英文字母组成

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/substring-with-concatenation-of-all-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路及方法

我看了官方题解,不是很懂,在看了一下其他作者的体节后,结合自己的思想,写出了应该算是滑动窗口解法的题解吧。

我把s中恰好可以由words中所有单词串联形成子串的对比单独写了一个方法,用了map计数,简单易懂。该方法传进来的参数有两个,一个是s的子串,一个是字符串数组words。

  • 首先用map记录words中每个字符串出现的次数,然后对s的字串进行滑动窗口,每一次滑动移动步数为step,即words数组元素的长度;
  • 然后将子串中出现的字符串在map中进行参照,出现则次数-1,未出现则代表words不能组成该子串;
  • 接着判断map中出现次数为0的字符串,进行删除操作;
  • 最后判定map是否为空,为空则代表该子串可以由 words 中所有单词串联形成。
    最后的最后,就是对原始字符串s进行滑动窗口。
class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> res = new ArrayList<>();
        int len = words.length * words[0].length();
        // 从首位开始遍历,寻找所有符合条件的字串起始位
        for (int i = 0; i <= s.length() - len; i++) {
            String cur = s.substring(i, i + len);
            if (isEquals(cur, words)) res.add(i);
        }

        return res;
    }

    /**
     * @description: 判断字符串s是否由words内字符串完全充分构成
     * @author: Abean
     * @date: 2022/7/15 15:50
     * @param: [s, words]
     * @return: 若参照map为空,则证明字符串s由words内字符串完全充分构成,返回true,否则false
     **/
    public Boolean isEquals(String s, String[] words) {
        Map<String, Integer> refer = new HashMap<>();
        // 统计words字符串次数
        for (String str : words) {
            refer.put(str, refer.getOrDefault(str, 0) + 1);
        }

        // 对比cur字符串中子串出现次数
        int n = s.length();
        int step = words[0].length();
        for (int i = 0; i <= n - step; i += step) {
            String cur = s.substring(i, i + step);
            // 出现则次数减一,否则输入字符串不由words数组内字符串组成
            if (refer.containsKey(cur)) {
                refer.put(cur, refer.get(cur) - 1);
            } else {
                return false;
            }
            // 若次数为0,删除该子串
            if (refer.get(cur) == 0) refer.remove(cur);
        }

        return refer.size() == 0;
    }
}

结果如下:

相关文章

网友评论

      本文标题:30. 串联所有单词的子串

      本文链接:https://www.haomeiwen.com/subject/soqcirtx.html