• [LeetCode] 792. Number of Matching Subsequences


    Given a string s and an array of strings words, return the number of words[i] that is a subsequence of s.

    A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.

    • For example, "ace" is a subsequence of "abcde"

    Example 1:

    Input: s = "abcde", words = ["a","bb","acd","ace"]
    Output: 3
    Explanation: There are three strings in words that are a subsequence of s: "a", "acd", "ace".
    

    Example 2:

    Input: s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"]
    Output: 2

    Constraints:

    • 1 <= s.length <= 5 * 104
    • 1 <= words.length <= 5000
    • 1 <= words[i].length <= 50
    • s and words[i] consist of only lowercase English letters.

    匹配子序列的单词数。

    给定字符串 s 和字符串数组 words, 返回  words[i] 中是s的子序列的单词个数 。

    字符串的 子序列 是从原始字符串中生成的新字符串,可以从中删去一些字符(可以是none),而不改变其余字符的相对顺序。

    例如, “ace” 是 “abcde” 的子序列。

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

    思路是桶排序。题意不难理解,给了一个字符串 s 和一串单词,请你计算有多少单词属于 s 的子序列。暴力解是把单词一个个拿出来看,用双指针的办法去跟 s 比较,看每个单词到底是不是 s 的子序列。这个做法可行,但是在 s 很长的情况下是会超时的。

    一个相对优化的思路是桶排序。这里我们创建一个hashmap<Character, deque<String>>,key是26个字母,value是一个队列,队列里存的是所有首字母为 X 的单词。

    首先第一轮初始化遍历 words 数组,把每个单词依据他们首字母的不同,放入 hashmap 的不同 key 下面。接着我们开始遍历字符串 s,每遇到一个字母 X,我们就去 hashmap 中拿出字母 X 背后对应的队列 queue。queue 中的单词都是首字母为 X 的单词。我们遍历这些单词,如果这时我们发现某个单词已经遍历完毕,说明这个单词就是 s 的子序列。对于没有遍历完的单词,去掉他的首字母,把 word.substring(1) 根据他当前新的首字母是什么,再放入hashmap中另外一个key背后的队列继续循环。

    举例,比如题目中的第一个例子,我们创建了hashmap之后,开始遍历 s = "abcde"。一开始我们发现是字母 a,符合首字母为 a 的单词有 "a","acd","ace"。其中因为 "a" 已经遍历完毕,所以他就是满足题意的一个子序列。对于 "acd" 和 "ace" ,我们去掉他们的首字母,把 "cd" 和 "ce" 加入 hashmap 中 key 为 "c" 的那个队列继续参与遍历。

    此时我们遍历到了字母 b,s = "abcde"。因为 hashmap 中没有首字母是 b 的单词所以直接看下一个字母。此时我们遍历到了字母 c,s = "abcde"。此时 "cd" 和 "ce" 都满足首字母为 "c",我们再把这两个单词分别去掉他们的首字母,再放回 hashmap 中 key 为 "d" 和 "e" 的队列。依据这个思路,最后 "cd" 和 "ce" 也都会被遇到,所以最后答案是有 3 个单词是 s 的子序列。

    时间O(n^2) - worst case,所有单词都是 s 的子序列且所有单词都跟 s 一样长

    空间O(n) - hashmap

    Java实现

     1 class Solution {
     2     public int numMatchingSubseq(String s, String[] words) {
     3         HashMap<Character, Deque<String>> map = new HashMap<>();
     4         for (char c = 'a'; c <= 'z'; c++) {
     5             map.put(c, new ArrayDeque<>());
     6         }
     7         // 把所有的单词按照首字母不同放入hashmap
     8         for (String word : words) {
     9             map.get(word.charAt(0)).offer(word);
    10         }
    11 
    12         int count = 0;
    13         for (char c : s.toCharArray()) {
    14             Deque<String> queue = map.get(c);
    15             int size = queue.size();
    16             for (int i = 0; i < size; i++) {
    17                 String word = queue.poll();
    18                 if (word.length() == 1) {
    19                     count++;
    20                 } else {
    21                     map.get(word.charAt(1)).offer(word.substring(1));
    22                 }
    23             }
    24         }
    25         return count;
    26     }
    27 }

    LeetCode 题目总结

  • 相关阅读:
    青云黄允松:2016年是云计算市场最关键的一年
    知道创宇CTO杨冀龙:网络安全人才决定行业格局
    su 与 su
    如何进入单用户模式(CentOS6.9)
    在虚拟机中还原GHO镜像系统
    安装CentOS 7 文字版
    把typora改为微软雅黑+Consolas
    使用python操作文件实现购物车程序
    使用python操作json文本文件
    资源下载网址集合
  • 原文地址:https://www.cnblogs.com/cnoodle/p/16497623.html
Copyright © 2020-2023  润新知