LeetCode题练习与总结:单词搜索Ⅱ--212

news2024/11/14 14:31:39

一、题目描述

给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words, 返回所有二维网格上的单词 。

单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

示例 1:

输入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
输出:["eat","oath"]

示例 2:

输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 12
  • board[i][j] 是一个小写英文字母
  • 1 <= words.length <= 3 * 10^4
  • 1 <= words[i].length <= 10
  • words[i] 由小写英文字母组成
  • words 中的所有字符串互不相同

二、解题思路

这个问题可以使用深度优先搜索(DFS)结合前缀树(Trie)来解决。首先,我们构建一个前缀树,将所有的单词插入到前缀树中。然后,我们遍历二维网格的每一个单元格,从每个单元格开始,使用深度优先搜索在网格中寻找匹配前缀树的单词。

以下是具体的步骤:

  1. 构建前缀树:创建一个Trie类,包含插入和查找方法。将所有的单词插入到前缀树中。

  2. 深度优先搜索:创建一个DFS方法,该方法接受当前单元格的位置、前缀树节点、网格、以及已经访问过的单元格集合。在DFS过程中,如果当前单元格的字符不在前缀树中,返回;否则,检查当前节点是否是一个单词的结尾,如果是,则将该单词添加到结果集中,并从前缀树中删除该单词,以避免重复添加。

  3. 遍历网格:遍历网格的每一个单元格,从每个单元格开始进行DFS搜索。

三、具体代码

class Solution {
    class TrieNode {
        TrieNode[] children = new TrieNode[26];
        String word;
    }

    class Trie {
        TrieNode root = new TrieNode();

        public void insert(String word) {
            TrieNode node = root;
            for (char c : word.toCharArray()) {
                if (node.children[c - 'a'] == null) {
                    node.children[c - 'a'] = new TrieNode();
                }
                node = node.children[c - 'a'];
            }
            node.word = word;
        }
    }

    public List<String> findWords(char[][] board, String[] words) {
        Trie trie = new Trie();
        for (String word : words) {
            trie.insert(word);
        }
        List<String> res = new ArrayList<>();
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                dfs(board, i, j, trie.root, res);
            }
        }
        return res;
    }

    private void dfs(char[][] board, int i, int j, TrieNode node, List<String> res) {
        if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || board[i][j] == '#' || node.children[board[i][j] - 'a'] == null) {
            return;
        }
        char c = board[i][j];
        node = node.children[c - 'a'];
        if (node.word != null) {
            res.add(node.word);
            node.word = null; // 避免重复添加
        }
        board[i][j] = '#'; // 标记为已访问
        dfs(board, i - 1, j, node, res);
        dfs(board, i + 1, j, node, res);
        dfs(board, i, j - 1, node, res);
        dfs(board, i, j + 1, node, res);
        board[i][j] = c; // 恢复现场
    }
}

在上述代码中,我们首先构建了一个Trie树,然后通过DFS在网格中搜索匹配的单词。在DFS过程中,我们使用#字符来标记已经访问过的单元格,以避免重复访问。当一个单词被找到时,我们从Trie树中移除该单词,确保不会重复添加到结果集中。最后,我们恢复单元格的原始字符,以便其他搜索路径可以使用该单元格。

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 构建Trie树:

    • 对于每个单词,我们遍历其所有字符并将其插入到Trie树中。假设单词列表words中总共有N个单词,每个单词的平均长度为L,则构建Trie树的时间复杂度为O(N * L)
  • 深度优先搜索(DFS):

    • 对于网格中的每个单元格,我们可能都会执行一次DFS搜索。网格大小为m * n,每个单元格最多会被访问4次(上、下、左、右)。
    • 在最坏的情况下,每次DFS搜索都会遍历整个网格,即每次DFS的时间复杂度为O(m * n)
    • 因此,所有DFS搜索的总时间复杂度为O(m * n * 4 * m * n),即O(4 * m^2 * n^2),简化后为O(m^2 * n^2)

综上所述,总的时间复杂度为构建Trie树的时间复杂度加上DFS的时间复杂度,即O(N * L + m^2 * n^2)

2. 空间复杂度
  • Trie树:

    • Trie树的空间复杂度取决于单词的数量和长度。在最坏的情况下,如果所有单词都是独特的,Trie树将包含所有单词的字符,空间复杂度为O(N * L)
  • DFS搜索:

    • DFS搜索需要递归栈空间,在最坏的情况下,递归深度为网格大小m * n,因此递归栈空间复杂度为O(m * n)
  • 结果列表:

    • 结果列表存储找到的单词,其空间复杂度取决于找到的单词数量,但不会超过单词列表的总数N,因此空间复杂度为O(N)

综上所述,总的空间复杂度为Trie树的空间复杂度加上DFS递归栈的空间复杂度加上结果列表的空间复杂度,即O(N * L + m * n + N)。由于N * L通常是最大的,因此可以简化为O(N * L)

五、总结知识点

  • 数据结构 - Trie树(前缀树)

    • Trie树是一种用于检索字符串数据集中的键的有序树结构,是一种高效的字符串查找数据结构。
    • 每个节点包含一个字符数组children,用于存储子节点,子节点的索引对应字符与’a’的差值。
    • 每个节点可能包含一个字符串word,用于标记该节点是否是某个单词的结束。
  • 递归 - 深度优先搜索(DFS)

    • DFS是一种用于遍历或搜索树或图的算法。
    • 在DFS中,代码通过递归函数dfs来探索所有可能的路径。
    • DFS的递归终止条件包括越界检查、已访问标记检查以及当前字符是否存在于Trie树中的子节点。
  • 字符串处理

    • 字符串转换为字符数组word.toCharArray(),以便遍历字符串中的每个字符。
    • 字符到索引的转换c - 'a',用于访问Trie树中相应的子节点。
  • 数组操作

    • 使用二维字符数组board表示网格。
    • 数组索引访问,例如board[i][j],用于访问网格中的单元格。
  • 集合操作

    • 使用List<String>来存储找到的单词。
    • 使用ArrayList作为具体的列表实现,提供动态数组的功能。
  • 逻辑控制

    • if语句用于条件判断,例如检查边界条件、字符是否匹配Trie树节点。
    • for循环用于遍历网格的每个单元格和单词列表的每个单词。
  • 标记与恢复

    • 使用特殊字符'#'来标记网格中的单元格已被访问,防止在DFS中重复访问。
    • 在完成当前路径的搜索后,恢复单元格的原始字符,以便其他路径可以使用该单元格。
  • 代码优化

    • 在找到单词后,立即将Trie树中对应节点的word字段设置为null,避免在后续搜索中重复添加相同的单词。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2091340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 scikit-learn 实战感知机算法

一 引言 感知机&#xff08;Perceptron&#xff09;是最早的人工神经网络模型之一&#xff0c;由 Frank Rosenblatt 在 1957 年提出。虽然它相对简单&#xff0c;但在处理线性可分问题时却非常有效。本文将介绍如何使用 Python 的 scikit-learn 库来实现感知机&#xff0c;并通…

SpringBoot SSM vue在线作业考试系统

SpringBoot SSM vue在线作业考试系统 首页 图片轮播 作业信息 通知公告 登录注册 留言板 个人中心 我的收藏 后台管理 登录注册 个人中心 教师信息管理 学生信息管理 学院信息管理 专业信息管理 班级信息管理 作业信息管理 作业提交管理 通知公告管理 试卷管理 试题管理 系统…

2024最新最全:网络安全人士【必备的30个安全工具】

1.Wireshark Wireshark&#xff08;前称Ethereal&#xff09;是一个网络封包分析软件。网络封包分析软件的功能是截取网络封包&#xff0c;并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口&#xff0c;直接与网卡进行数据报文交换。 2.Metasploit Meta…

Qt窗口 菜单栏 QMenuBar和的使用及说明

目录 1. 创建QT工程2. Qt5中添加资源文件3. 在Qt图形化界面创建菜单栏各组件4. 为菜单栏添加的选项增加图标5. 将菜单栏增加的功能拖动到工具栏6. 点击运行按钮查看运行结果7. 为菜单栏和工具栏增加的按钮添加相应的槽函数 1. 创建QT工程 打开Qt Creator软件&#xff0c;选择菜…

卧室无主灯照明布局:打造温馨舒适的私密空间

在追求温馨舒适的居家环境中&#xff0c;卧室作为休憩与放松的私密空间&#xff0c;其照明设计显得尤为重要。无主灯设计以其灵活多变、氛围营造独特的特点&#xff0c;正逐渐成为卧室照明的热门选择。那么&#xff0c;如何在卧室中实现无主灯的最佳布局呢&#xff1f;今天&…

【Python实战因果推断】73_图因果模型8

目录 Adjusting for Selection Bias Conditioning on a Mediator Adjusting for Selection Bias 不幸的是&#xff0c;纠正选择偏倚绝非易事。在我们一直在讨论的例子中&#xff0c;即使有随机对照试验&#xff0c;ATE也无法识别&#xff0c;仅仅是因为你无法在对那些回应了…

【精选】基于Django开发的静思阁自习预约管理系统(全网最新项目,独一无二)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

视频结构化从入门到精通——视频结构化技术应用难点

视频结构化技术应用难点 随着视频数据在智能安防、智能交通、零售分析等领域的广泛应用&#xff0c;视频结构化技术成为了提取视频信息的关键。然而&#xff0c;在实际应用中&#xff0c;这项技术面临着诸多挑战。本文将深入探讨这些难点&#xff0c;并提供可能的解决方案和未…

saas收银系统源码(附部分代码截图)

随着时代不断发展&#xff0c;很多连锁品牌不断涌现&#xff0c;门店数量也日益增多&#xff0c;但连锁品牌在选收银系统时&#xff0c;如果选择传统的SaaS模式合作&#xff0c;按门店数量、按功能模块收取服务费&#xff0c;门店数量如果多&#xff0c;每年也会是一笔不小的开…

SQL进阶技巧:近N指标如何精确计算并扩充?

目录 0 场景描述 1 数据准备 2 问题分析 3 小结 0 场景描述 假设表price 有三个字段 用户: user_id 日期:dt 订单金额 price,求每个用户的近N天的消费金额 近N指标的种类多,且日期跨度近期密,远期大。表price : 结果: 近N:rds(recent_days) dt user_id rds…

8月31日微语报,星期六,农历七月廿八

8月31日微语报&#xff0c;星期六&#xff0c;农历七月廿八&#xff0c;周末愉快&#xff01; 一份微语报&#xff0c;众览天下事&#xff01; 1、川渝地区正经历同期罕见高温&#xff0c;与高压天气系统和地形有关。 2、全国超六成GDP增量产自59城&#xff0c;深圳超京沪居…

缓存:浅谈双写导致的数据一致性问题

从理论上来说&#xff0c;给缓存设置过期时间&#xff0c;是保证最终一致性的解决方案。这种方案下&#xff0c;我们对存入缓存的数据设置过期时间&#xff0c;所有的写操作以数据库为准&#xff0c;对缓存操作只是尽最大努力更新即可。也就是说如果数据库写成功&#xff0c;缓…

爬虫入门urllib 和 request (一)

前言 在开始进行爬虫的知识之前&#xff0c;我们需要明白web网页是怎么工作的&#xff1f;浏览器工具是怎么使用的&#xff1f;反爬虫的手段手段是那些&#xff1f; 一.web请求全过程解析 我们浏览器在输入完网址到我们看到网页的整体内容, 这个过程中究竟发生了些什么? 我…

JavaEE 第21节 UDP数据报结构剖析

目录 前言报文结构1、源端口号&目的端口号2、UDP长度3、校验和概念校验和计算方法 前言 本篇文章会围绕UDP报文的结构&#xff0c;对此协议展开详细的讲解&#xff0c;比如报文中每个字段的作用、以及填写方式。 阅读完这篇文章&#xff0c;你会对UDP数据报结构有个透彻的…

不知道电脑驱动软件哪个好,试试这几款免费不限速的驱动安装软件

每一台电脑都需要安装相关的驱动才能保证设备的正常运行&#xff0c;然而&#xff0c;很多用户搜索下载的驱动安装软件不是捆绑各类软件就是限速下载或者需要开通会员。下面小编就来和大家分享几款免费且不限速的驱动安装软件&#xff0c;帮助大家找到最适合自己的驱动管理工具…

idea使用maven

文章目录 IDEA集成Maven配置Maven环境 全局配置&#xff1a;创建Maven项目POM配置详解 IDEA集成Maven 我们要想在IDEA中使用Maven进行项目构建&#xff0c;就需要在IDEA中集成Maven 配置Maven环境 当前工程设置 1、选择 IDEA中 File > Settings > Build,Execution,Dep…

7,sql 基本的创建库表查询数据

-- 创建库 CREATE DATABASE IF NOT EXISTS test04_dql; 切换到这个库USE test04_dql;-- 创建员工表 DROP TABLE IF EXISTS t_employee; ---创建字段CREATE TABLE t_employee (eid INT NOT NULL COMMENT 员工编号,ename VARCHAR(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900…

网站建设完成后, 做seo必须知道的专业知识之--黑帽SEO

黑帽SEO是指通过不道德或不公平的手段&#xff0c;试图提高网站在搜索引擎中的排名。下面将详细探讨黑帽SEO的各个方面&#xff1a; 定义与原理 定义概述&#xff1a;黑帽SEO涉及使用作弊策略和技巧&#xff0c;目的在于快速提升网站的搜索引擎排名&#xff0c;而非通过正当的…

Django+Vue音乐推荐系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 需要的环境3.2 Django接口层3.3 实体类3.4 config.ini3.5 启动类3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作者&…

C语言试题生成与考试系统/在线考试系统/试题管理系统

摘要 学生考试实现智能化管理的帮手需要有试题生成与考试系统&#xff0c;这样能够提高管理员的管理效率&#xff0c;试题生成与考试系统需要提供给用户查询的功能。计算机网络如果结合使用信息管理系统&#xff0c;能够提高管理员管理的效率&#xff0c;改善服务质量。优秀的…