• 图解LeetCode——792. 匹配子序列的单词数(难度:中等)


    一、题目

    给定字符串 s 和字符串数组 words, 返回  words[i] 中是s子序列的单词个数 。 字符串的 子序列 是从原始字符串中生成的新字符串,可以从中删去一些字符(可以是none),而不改变其余字符的相对顺序。

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

    二、示例

    2.1> 示例 1:

    【输入】 s = "abcde", words = ["a","bb","acd","ace"]
    【输出】 3
    【解释】 有三个是 s 的子序列的单词: "a", "acd", "ace"。

    2.2> 示例 2:

    【输入】 s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"]
    【输出】 2

    提示:

    • 1 <= s.length <= 5 * 10^4
    • 1 <= words.length <= 5000
    • 1 <= words[i].length <= 50
    • words[i]和 s 都只由小写字母组成。

    三、解题思路

    根据题目描述,需要我们去words字符串数组中却判断,哪些是字符串s子序列,最后再将子序列的总个数返回回来。那么,对于字符串子序列,我们主要关心如下两点:

    是否存在?】子序列中的某个字符是否在字符串s中存在。
    顺序对吗?】子序列中字符出现的顺序是否违背了字符串s中的顺序。

    那么针对这两种关注点,我们首先遍历字符串s中的每个字符,由于这些字符都是由小写字母构成,所以我们可以通过采用:字符减去‘a’来确定下标位置,并将该字符在s中出现的位置保存到ArrayList集合中。

    然后,我们再分别遍历字符串数组words中的每个字符串,逐一判断每个字符出现的位置顺序是否与s相同,如果不同,则可以判断该字符串不是s的子序列。具体操作详情请见下图:

    四、代码实现

    1. class Solution {
    2.     public int numMatchingSubseq(String s, String[] words) {
    3.         List<Integer>[] sm = new ArrayList[26]; // index:字符  sm[index]:字符出现的位置集合
    4.         char[] sc = s.toCharArray();
    5.         for (int i = 0; i < sc.length; i++) {
    6.             if (sm[sc[i]-'a'== null) sm[sc[i]-'a'= new ArrayList<>();
    7.             sm[sc[i]-'a'].add(i);
    8.         }
    9.         int result = words.length// 初始化result数量为所有单词,如果不满足条件,则陆续执行减1操作
    10.         for (String word : words) { // 遍历每个单词
    11.             int compareIndex = -1index;
    12.             for (int i = 0; i < word.length(); i++) { // 遍历每个字符
    13.                 if (sm[word.charAt(i)-'a'== null || 
    14.                         ((index = findCharIndex(compareIndex, sm[word.charAt(i)-'a'])) <= compareIndex)) {
    15.                     result--;
    16.                     break;
    17.                 }
    18.                 compareIndex = index;
    19.             }
    20.         }
    21.         return result;
    22.     }
    23.     // 折半查找
    24.     private int findCharIndex(int compareIndex, List<Integer> list) {
    25.         int head = 0, tail = list.size() - 1, mid;
    26.         while (head < tail) {
    27.             mid = head + (tail - head) / 2;
    28.             if (list.get(mid) > compareIndex) tail = mid;
    29.             else head = ++mid;
    30.         }
    31.         return list.get(head);
    32.     }
    33. }

     今天的文章内容就这些了:

    写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享 。

    更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

  • 相关阅读:
    SPL-安装与基本使用(二)
    软件测试/测试开发丨ChatGPT在测试计划中的应用策略
    极简c++(7)类的继承
    再再肝3天,整理了70个Python面向对象编程案例,怎能不收藏?
    小谈设计模式(21)—迭代器模式
    【Vim】VSCode下 Vim 插件配置自动切换中英文输入法
    mediasoup-client的H5在ios的微信内置浏览器上无法视频通话,报错device not supported
    使用PostMan测试WebService接口
    TiDB Lightning 故障处理
    sop作业指导书怎么做?sop标准作业指导书用什么软件做?
  • 原文地址:https://blog.csdn.net/qq_26470817/article/details/127897889