首页 > 其他分享 >​​leet code 30.串联所有单词的子串

​​leet code 30.串联所有单词的子串

时间:2023-10-28 14:02:17浏览次数:36  
标签:子串 map leet code 串联 30 length words 字符串

leet code 30.串联所有单词的子串

题目描述

给定一个字符串 s 和一个字符串数组 words

words 中所有字符串 长度相同

s 中的 串联子串 是指

  • 一个包含 words 中所有字符串以任意顺序排列连接起来的子串。
  • 例如,如果 words = ["ab","cd","ef"],
  • 那么 "abcdef", "abefcd","cdabef", "cdefab","efabcd", 和 "efcdab" 都是串联子串。
  • "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。

返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。

示例 1:

输入:

s = "barfoothefoobarman",

words = ["foo","bar"]

输出:[0,9]

解释:

  • 因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。 子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
  • 子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。 输出顺序无关紧要。返回 [9,0] 也是可以的。

示例 2:

输入:

s = "wordgoodgoodgoodbestword",

words = ["word","good","best","word"]

输出:[]

解释:

  • 因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
  • s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。 所以我们返回一个空数组。

示例 3:

输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]

输出:[6,9,12]

解释:

  • 因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
  • 子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。
  • 子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。
  • 子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。

提示:

  • ​​leet code 30.串联所有单词的子串_字符串
  • ​​leet code 30.串联所有单词的子串_字符串_02
  • ​​leet code 30.串联所有单词的子串_子串_03
  • words[i] 和 s 由小写英文字母组成

题目解析

由题目可知

  • words 数组中每一个单词的长度都相同,结合数组长度可以计算出 “串联子串” 的长度
  • len(串联子串) = n(数组长度) * singleLen(单个字符串长度)
  • 那么需要从给定的字符串 s 中寻找符合条件的 “串联子串” 的开始索引
  • 比较容易想到通过长度为 len 的窗口去遍历 字符串 s
  • 然后接下来问题变成:如何验证 当前遍历到的字符串 是不是 一个符合条件的“串联子串”
  • 一个比较直接的办法
  • 处理字符串,提取每一个单词并放到map集合中去
  • 然后把 words 数组的单词也放到 map 集合中去
  • 对比两个map是否相同

show code

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        int n = words.length;
        int singleWordLen = words[0].length();
        // 总长度
        int len = n * singleWordLen;
        // 结果集合
        List<Integer> ans = new ArrayList<>();
        if(len > s.length()) {
            return ans;
        }
        // 总长度作为滑动窗口去遍历字符串 s
        // 然后验证 窗口内的子串 是否是 words 数组其中一种可能的排列.

        // 把 words 转存成 map
        Map<String, Integer> wMap = new HashMap<>();
        for (String word : words) {
            wMap.put(word, wMap.getOrDefault(word, 0) + 1);
        }

        // 遍历 s .
        for (int i = 0; i <= s.length() - len; i++) {
            //  滑动窗口  [i, i + len]
            if(check(s.substring(i, i + len), wMap, singleWordLen)) {
                ans.add(i);
            }
        }

        return ans;
    }

    private boolean check(String s, Map<String, Integer> wMap, int len) {
        // 现在问题变成了,验证 字符串 s 是否是 words 数组的全排列可能之一.
        // 首先可以确定的事情是 : s 的长度和 words 中所有子串的长度相同.
        // 需要找到一个比较好的验证方法.
        // 如何验证?

        // 是不是可以统计 words 中所有单词出现的次数?然后双重遍历

        Map<String, Integer> map = new HashMap<>();
        // 解析 字符串 s 转存成 map
        int n = s.length();
        for (int i = 0; i < n; i += len) {
            String word = s.substring(i, i + len);
            map.put(word, map.getOrDefault(word, 0) + 1);
        }

        for (Map.Entry<String, Integer> entry : wMap.entrySet()) {
            if(map.containsKey(entry.getKey()) && Objects.equals(entry.getValue(), map.get(entry.getKey()))) {
                continue;
            } else {
                return false;
            }
        }


        return true;
    }
}

标签:子串,map,leet,code,串联,30,length,words,字符串
From: https://blog.51cto.com/u_16079703/8070009

相关文章

  • CodeForces 1887D Split
    洛谷传送门CF传送门\(a_l,a_{l+1},\ldotsa_r\)是好的当且仅当\(\existsk\in[l,r-1],\max\limits_{i=l}^ka_i<\min\limits_{i=k+1}^ra_i\),称此时的\(k\)为分割点。对\(r\)扫描线,单调栈维护极长的一些区间\([L_i,R_i]\)使得\(\min\limits_{j=......
  • 2023-2024-1 20211306 密码系统设计与实现课程学习笔记7
    20211306密码系统设计与实现课程学习笔记7任务详情自学教材第4章,提交学习笔记知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容“我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题......
  • 麒麟KYLINOS2303版本上使用KDE桌面共享软件
    往期文章:龙芯3A5000上安装软件hello,大家好啊,今天给大家推荐一个在麒麟KYLINOS桌面操作系统2303版本上使用KDE桌面共享软件的文章,通过安装KDE桌面共享软件,可以让远程vnc客户端连接访问本机桌面,进行一系列的远程操作,欢迎大家分享转发。关注我吧!1、查看系统信息pdsyw@pdsyw-pc:~/桌面$......
  • vs code markdown mermaid预览插件安装
    安装预览插件预览指令使用control+shift+p效果......
  • LeetCode 11. 盛最多水的容器
    盛水最多的容器题目链接11.盛最多水的容器给定一个长度为n的整数数组height。有n条垂线,第i条线的两个端点是(i,0)和(i,height[i])。找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。**说明:**你不能倾斜容器。示例1:......
  • LeetCode 202. 快乐数
    快乐数题目链接202.快乐数编写一个算法来判断一个数n是不是快乐数。「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为1,也可能是无限循环但始终变不到1。如果这个过程结果为1,那么这个数就是快乐数。如果n......
  • Leetcode 1089. 复写零
    复写零题目链接1089.复写零给你一个长度固定的整数数组arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。注意:请不要在超过该数组长度的位置写入元素。请对输入的数组就地进行上述修改,不要从函数返回任何东西。示例1:输入:arr=[1,0,2,3,0,4,5,0]输出:[1,0,0,......
  • LeetCode 611. 有效三角形的个数
    有效三角形的个数题目链接611.有效三角形的个数给定一个包含非负整数的数组nums,返回其中可以组成三角形三条边的三元组个数。示例1:输入:nums=[2,2,3,4]输出:3解释:有效的组合是:2,3,4(使用第一个2)2,3,4(使用第二个2)2,2,3示例2:输入:nums=[4,2,3,4]输出:......
  • Leetcode 283. 移动零
    移动零题目链接283.移动零给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请注意,必须在不复制数组的情况下原地对数组进行操作。示例1:输入:nums=[0,1,0,3,12]输出:[1,3,12,0,0]示例2:输入:nums=[0]输出:[0]题目解释这道题目......
  • [TopCoder 13001] BigO 题解
    [TopCoder13001]BigO题解题目描述给定一张有向图,当\(L\)趋近于无穷大时,长度为\(L\)的路径条数有\(S\)条,此时若\(S=O(L^k)\),输出\(k\),否则如果没有多项式的大O表示法,输出\(-1\)。指数情况首先如果一张图中存在如下强连通分量,则\(S=O(2^L)\)。因为每次到1......