当前位置: 首页 > news >正文

【LeetCode 每日一题】966. 元音拼写检查器

Problem: 966. 元音拼写检查器

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(W*L + Q*L)
    • 空间复杂度:O(W*L)

整体思路

这段代码旨在实现一个具有特定纠错规则的拼写检查器。它接收一个正确的单词列表 wordlist 和一个待检查的查询列表 queries,然后根据三条优先级递减的规则来匹配或纠正每个查询。

算法的核心策略是 预处理 + 快速查找。它首先通过一次遍历 wordlist 来构建几个高效的查找数据结构(哈希集合和哈希映射),然后在处理 queries 时,利用这些预处理好的数据结构进行快速匹配。

  1. 匹配规则(按优先级)

    1. 完全匹配:查询词与 wordlist 中的某个词完全一样(包括大小写)。
    2. 忽略大小写匹配:查询词在忽略大小写后,与 wordlist 中的某个词(同样忽略大小写)匹配。
    3. 元音错误匹配:查询词在忽略大小写,并将所有元音字母替换为通用占位符(如 *)后,与 wordlist 中某个词经过同样处理后的模式相匹配。
  2. 预处理阶段(构建查找表)

    • Set<String> origin: 用于规则1。这是一个哈希集合,存储了 wordlist 中所有原始单词,可以提供 O(1) 的平均时间复杂度的精确查找。
    • Map<String, String> lowerToOrigin: 用于规则2。这个哈希映射的键是 wordlist 中单词的小写形式,值是对应的原始单词。这使得忽略大小写的匹配变得非常快。
    • Map<String, String> vowelToOrigin: 用于规则3。这个哈希映射的键是一个“元音模糊”的模式(例如,“Kitten” -> “kttn”),值是对应的原始单词。这是通过一个辅助函数 replaceVowels 来生成模式的。
    • 重要细节(处理首次出现):代码在填充 lowerToOriginvowelToOrigin 时,从后向前遍历 wordlist。这是为了处理一个隐含的规则:如果多个 wordlist 中的单词在忽略大小写或元音后匹配同一个查询,应返回在 wordlist首次出现的那个。通过从后向前 put,如果遇到冲突的键,后面的值会覆盖前面的,最终保留在map中的就是 wordlist 中最靠前的那个单词。
  3. 查询处理阶段

    • 算法遍历每一个 query
    • 它严格按照上述三条规则的优先级进行检查:
      • 首先,在 origin 集合中查找,如果找到,说明是完全匹配,当前查询词正确,跳过。
      • 如果上一步失败,将 query 转为小写,在 lowerToOrigin 映射中查找,如果找到,就用映射中的原始单词替换当前查询词。
      • 如果上一步仍失败,将小写的 query 转换为“元音模糊”模式,在 vowelToOrigin 映射中查找。如果找到,就用映射中的原始单词替换;如果找不到,说明没有任何匹配,根据规则替换为空字符串 ""

完整代码

import java.util.*;class Solution {/*** 根据特定规则对查询词进行拼写检查和纠正。* @param wordlist 正确的单词列表* @param queries  待检查的查询词列表* @return 纠正后的查询词列表*/public String[] spellchecker(String[] wordlist, String[] queries) {int n = wordlist.length;// 查找表 1: 用于完全匹配(区分大小写)Set<String> origin = new HashSet<>(Arrays.asList(wordlist));// 查找表 2: 用于忽略大小写匹配。Key: 小写词, Value: 原始词Map<String, String> lowerToOrigin = new HashMap<>(n);// 查找表 3: 用于元音错误匹配。Key: 元音模糊模式, Value: 原始词Map<String, String> vowelToOrigin = new HashMap<>(n);// 预处理阶段:从后向前遍历 wordlist 以构建查找表// 从后向前是为了确保当有多个词匹配同一模式时,保留在 wordlist 中首次出现的那个for (int i = n - 1; i >= 0; i--) {String s = wordlist[i];String lower = s.toLowerCase();// 填充忽略大小写的查找表lowerToOrigin.put(lower, s);// 填充元音模糊的查找表vowelToOrigin.put(replaceVowels(lower), s);}// 查询处理阶段for (int i = 0; i < queries.length; i++) {String s = queries[i];// 规则 1: 完全匹配if (origin.contains(s)) {// 匹配成功,无需修改,继续下一个查询continue;}String lower = s.toLowerCase();// 规则 2: 忽略大小写匹配if (lowerToOrigin.containsKey(lower)) {queries[i] = lowerToOrigin.get(lower);} else {// 规则 3: 元音错误匹配// 如果前两条规则都失败,则尝试此规则// getOrDefault 可以在找不到匹配时优雅地返回默认值 ""queries[i] = vowelToOrigin.getOrDefault(replaceVowels(lower), "");}}return queries;}/*** 辅助函数:将字符串中的所有元音替换为 '*',生成一个元音模糊的模式。* @param lower 输入的小写字符串* @return 元音模糊模式字符串*/private String replaceVowels(String lower) {char[] s = lower.toCharArray();for (int i = 0; i < s.length; i++) {char c = s[i];if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {s[i] = '*';}}return new String(s);}
}

时空复杂度

  • Wwordlist 的长度。
  • Qqueries 的长度。
  • L 为单词的最大长度。

时间复杂度:O(WL + QL)

  1. 预处理阶段

    • 遍历 wordlist W 次。
    • 在循环内部,toLowerCase()replaceVowels() 都需要遍历单词,时间复杂度为 O(L)。
    • HashSet.add()HashMap.put() 操作,对于字符串键,平均时间复杂度也是 O(L)(因为需要计算哈希值和进行比较)。
    • 因此,预处理阶段的总时间复杂度为 W * O(L) = O(W*L)
  2. 查询处理阶段

    • 遍历 queries Q 次。
    • 在循环内部,contains(), get(), toLowerCase(), replaceVowels() 等操作的平均时间复杂度都是 O(L)。
    • 因此,查询阶段的总时间复杂度为 Q * O(L) = O(Q*L)

综合分析
总的时间复杂度是两个阶段之和,即 O(WL + QL)

空间复杂度:O(W*L)

  1. 主要存储开销:算法创建了三个数据结构来存储预处理信息。
    • origin 集合:存储了 W 个单词,总空间占用与所有单词的总长度成正比,即 O(W*L)
    • lowerToOrigin 映射:存储了 W 个键值对,总空间占用也是 O(W*L)
    • vowelToOrigin 映射:存储了 W 个键值对,总空间占用同样是 O(W*L)
  2. 辅助空间:在 replaceVowels 中创建的临时 char[] 数组大小为 O(L),但这不影响整体复杂度。

综合分析
算法所需的额外空间主要由这三个查找表决定。因此,总的空间复杂度为 O(W*L)

参考灵神

http://www.dtcms.com/a/394946.html

相关文章:

  • windows 服务器如何开启系统自带的ftp服务
  • 2025年面试经历
  • Linux 基础:目录结构
  • OpenLayers地图交互 -- 章节七:指针交互详解
  • Kafka实战案例一:阿里云Kafka智能设备数据实时处理系统
  • 回调函数与错误处理
  • 深入大模型-2-大模型微调之Windows10安装大语言模型Unsloth微调环境
  • openssl x509 -noout -text -in server.cert.pem输出字段详解
  • Linux 基础:Vi/Vim 编辑器
  • K8s和Service Mesh如何强化微服务治理能力
  • 知识图谱赋能自然语言处理的深层语义分析:技术、影响与前沿趋势
  • 论文笔记:How Can Recommender Systems Benefit from Large Language Models: A Survey
  • idea终端添加git-bash,支持linux的shell语法
  • MITRE ATLAS对抗威胁矩阵:守护LLM安全的中国实践指南
  • 常见的 Web 项目性能优化方法有哪些?​​也适用于首页
  • Qt QMainWindow类深度解析:主窗口框架的核心实现
  • 知识图谱对自然语言处理深层语义分析的革命性影响与启示
  • 内部标识符
  • 计算机网络2
  • 计算机视觉(opencv)实战三十二——CascadeClassifier 人脸微笑检测(摄像头)
  • MyBatis-Plus 全方位深度指南:从入门到精通
  • PyTorch 神经网络工具箱:从组件到基础工具,搭建网络的入门钥匙
  • 分布式专题——18 Zookeeper选举Leader源码剖析
  • JVM 调优在分布式场景下的特殊策略:从集群 GC 分析到 OOM 排查实战(二)
  • 基于OpenEuler部署kafka消息队列
  • Flink TCP Channel复用:NettyServer、NettyProtocol详解
  • Sass和Less的区别【前端】
  • Kotlin互斥锁Mutex协程withLock实现同步
  • Seedream 4.0 测评|AI 人生重开:从极速创作到叙事实践
  • vscode clangd 保姆教程