[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 题目总结

posted @ 2022-07-20 13:28  CNoodle  阅读(74)  评论(0编辑  收藏  举报