LeetCode_前缀树_困难_212.单词搜索 II

news2024/11/19 15:35:04

目录

  • 1.题目
  • 2.思路
  • 3.代码实现(Java)

1.题目

给定一个 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 * 104
1 <= words[i].length <= 10
words[i] 由小写英文字母组成
words 中的所有字符串互不相同

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/word-search-ii

2.思路

(1)回溯
本题可以在79.单词搜索这题的之上,对 words 中的所有 word 进行判断即可,最终结果保存到 res 中。但是该方法的时间复杂度较高,因此在 LeetCode 中提交时会显示“超出时间限制”的提示!

(2)回溯 & 字典树
思路参考本题官方题解。

相关题目:
LeetCode_回溯_中等_79.单词搜索

3.代码实现(Java)

//思路1————回溯
class Solution {

    //定义上、下、左、右这 4 个方向
    int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public List<String> findWords(char[][] board, String[] words) {
        List<String> res = new ArrayList<>();
        for (String word : words) {
            if (exist(board, word)) {
                res.add(word);
            }
        }
        return res;
    }

    public boolean exist(char[][] board, String word) {
        int m = board.length;
        int n = board[0].length;
        /*
            visited[i][j] == true 表示在每一轮搜索中,字符 board[i][j] 已经访问过了
            此处的每一轮搜索指的是以二维字符网格 board 中的每一个字符作为起点开始搜索,当每访问一个字符 board[i][j],
            就将 visited[i][j] 设置为 true,当该轮搜索结束后,再将 visited[i][j] 设置为 false
        */
        boolean[][] visited = new boolean[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                //遍历二维字符网格 board,每遇到一个字符 board[i][j],就以它为起点开始搜索 word
                if (judge(i, j, word, 0, board, visited)) {
                    return true;
                }
            }
        }
        return false;
    }

    /* 
        i、j: 表示当前正在访问的二维字符网格中字符的横坐标和纵坐标
        k: 表示匹配 word 中字符的下标
    */
    public boolean judge(int i, int j, String word, int k, char[][] board, boolean[][] visited) {
        if (board[i][j] != word.charAt(k)) {
            return false;
        } else if (word.length() - 1 == k) {
            // word 的每一个字符都已匹配成功,即 word 存在于网格中,返回 true
            return true;
        }
        //字符 board[i][j] 在此轮搜索中已经被访问过
        visited[i][j] = true;
        boolean flag = false;
        //分别向 4 个方向开始搜索
        for (int[] dir : dirs) {
            int newi = i + dir[0];
            int newj = j + dir[1];
            if (newi >= 0 && newj >= 0 && newi < board.length && newj < board[0].length) {
                if (!visited[newi][newj] && judge(newi, newj, word, k + 1, board, visited)) {
                    flag = true;
                    break;
                }
            }
        }
        //本轮搜索结束
        visited[i][j] = false;
        return flag;
    }
}
//思路2————回溯 & 字典树
import java.util.*;

class Solution {
    //定义上、下、左、右这 4 个方向
    int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    int m, n;

    public List<String> findWords(char[][] board, String[] words) {
        m = board.length;
        n = board[0].length;
        Trie trie = new Trie();
        for (String word : words) {
            trie.insert(word);
        }
        Set<String> res = new HashSet<>();
        //遍历整个 board
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                dfs(board, trie, i, j, res);
            }
        }
        return new ArrayList<>(res);
    }

    public void dfs(char[][] board, Trie curTrie, int i, int j, Set<String> res) {
        if (!curTrie.children.containsKey(board[i][j])) {
            return;
        }
        char c = board[i][j]; 
        curTrie = curTrie.children.get(c);
        if (!"".equals(curTrie.word)) {
            res.add(curTrie.word);
        }
        board[i][j] = '#';
        for (int[] dir : dirs) {
            int nextI = i + dir[0];
            int nextJ = j + dir[1];
            //判断边界条件
            if (nextI >= 0 && nextI < m && nextJ >= 0 && nextJ < n) {
                dfs(board, curTrie, nextI, nextJ, res);
            }
        }
        board[i][j] = c;
    }
}

class Trie {
    String word;
    Map<Character, Trie> children;

    public Trie() {
        this.word = "";
        this.children = new HashMap<>();
    }

    public void insert(String word) {
        Trie cur = this;
        for (int i = 0; i < word.length(); ++i) {
            char c = word.charAt(i);
            if (!cur.children.containsKey(c)) {
                cur.children.put(c, new Trie());
            }
            cur = cur.children.get(c);
        }
        cur.word = word;
    }
}

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

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

相关文章

网络安全学术顶会——SP 2023 议题清单、摘要与总结(中)

注&#xff1a;本文由ChatGPT与Claude联合生成 51、Effective ReDoS Detection by Principled Vulnerability Modeling and Exploit Generation 正则表达式拒绝服务攻击&#xff08;ReDoS&#xff09;是一种算法复杂度攻击。对于易受攻击的正则表达式&#xff0c;攻击者可以精心…

kotlin学习(一)基本概念、数据对象类型、控制流程、空值检验、类与接口

文章目录 认识Kotlin跨平台特性语言类型java的语言类型kotlin的运行原理 hello world 基本概念程序入口数据与对象类型 和 显式数字转换浮点类型位运算AnyUnitNothing 声明变量只读变量 val与可变变量var查看Kotlin字节码 fun&#xff08;方法 / 函数&#xff09;函数参数默认值…

MindMapper 思维导图 21.x

MindMapper 可视化绘图软件是任何想要快速组织思想和想法的人的必备工具。MindMapper 具有易于使用的界面&#xff0c;可以轻松创建可用于头脑风暴、决策制定和项目管理的综合思维导图。MindMapper 还是一个非常强大的生产力工具&#xff0c;因为它允许用户跟踪他们在项目和任务…

Linux GCC,GDB,Shell脚本的简单使用

这里写目录标题 GCC命令GDB命令Shell脚本 GCC命令 GCC&#xff08;GNU Compiler Collection&#xff0c;GNU编译器套件&#xff09;是由GNU开发的编程语言译器 编译一个简单的.c程序&#xff1a; 四步分开写&#xff1a; gcc -E -o hello.i hello.c // 预处理 gcc -S -o he…

49、基于51单片机无刷电机调速系统设计(程序+原理图+PCB图+英文文献+参考论文+开题报告+元器件清单等)

摘 要 由于电机的发展&#xff0c;电动机由之前的带有刷子变换为无刷子直流电动机&#xff0c;其内部结构是电子换向器&#xff0c;而不是传统的机械式换向器&#xff0c;电动机的组成为永磁材料制造的转子和带有线圈绕组的定子组成。 所以本论文思路在全面分析无刷直流电机…

Tuleap ,一个用于软件项目管理的平台

Eclipse 基金会使用 Tuleap 取代了 Bugzilla,Tuleap 是一个独特的开源项目管理工具&#xff0c;目前发展势头很好&#xff0c;现在&#xff0c;每个月它会出一个大版本。它还被列在2015 年五大开源项目管理工具和 2016 年十一个名列前茅项目管理工具中。 Manuel Vacelet 是开发…

【MySQL】一文带你了解MySQL的基础知识

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集&#xff01; &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指…

【Docker】docker部署springboot+vue+mysql+nginx前后端分离项目【实战篇】

文章目录 1、docker 安装jdk2、docker 安装mysql通过Docker命令进入Mysql容器内部初始化数据sqlDbx连接查看 3、docker build构建后端镜像修改配置数据库JDBC链接IP为虚拟机服务器IPmaven clean package打包后端jar并上传到服务器编写Dockfilebuild 构建查看构建的后端镜像app …

51单片机读取DS18B20温度传感器

1.首先我们知道DS18B20是单总线协议&#xff0c;只有一根数据线。所以Data数据线即使发送端又是接收端&#xff0c;同时DS18B20内部接了弱上拉电阻&#xff08;如图一所示&#xff09;&#xff0c;数据线默认为高电平。有了这些概念&#xff0c;我们就能进行下一步。 图一&…

1738_创建自己的simulink模块库

全部学习汇总&#xff1a; GreyZhang/g_matlab: MATLAB once used to be my daily tool. After many years when I go back and read my old learning notes I felt maybe I still need it in the future. So, start this repo to keep some of my old learning notes servral …

随着网络犯罪策略的转变,暗网威胁瞄准能源行业

根据 Searchlight Cyber 的一份报告&#xff0c;能源行业越来越多地通过暗网上的活动成为恶意行为者和威胁组织的目标。 该报告详细介绍了威胁行为者出售全球能源组织初始访问权的众多实例。 其中包括美国、加拿大、英国、法国、意大利和印度尼西亚的流行暗网论坛&#xff08…

使用AIGC工具巧用Linux系统

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

【Python爬虫开发基础③】Python基础(文件操作方法汇总)

友情提示&#xff1a;由于本专栏的文章偏向于爬虫&#xff0c;所以对于python的介绍不可能面面俱到&#xff0c;在这里只讲重点。 如果大家觉得有没讲到的地方&#xff0c;欢迎补充~ 往期推荐&#xff1a; 【Python爬虫开发基础①】Python基础&#xff08;变量及其命名规范&…

黑马Redis视频教程高级篇(三:最佳实践)

目录 一、Redis键值设计 1.1、优雅的key结构 1.2、拒绝BigKey 1.2.1、BigKey的危害 1.2.2、如何发现BigKey 1.2.3、如何删除BigKey 1.3、恰当的数据类型 例1&#xff1a;比如存储一个User对象&#xff0c;我们有三种存储方式&#xff1a; 例2&#xff1a;假如有hash类…

5.部署LVS-DR群集

文章目录 部署LVS-DR群集LVS-DR数据包流向分析LVS-DR中的ARP问题问题一问题二 LVS-DR部署调度器配置节点服务器配置NFS服务器配置 ipvsadm 部署LVS-DR群集 LVS-DR数据包流向分析 为方便进行原理分析&#xff0c;将Client与群集机器放在同一网络中&#xff0c;数据包流经的路线…

2000-2019年280多个地级市就业人数数据(全市)/城市就业数据

2000-2019年280多个地级市就业人数数据&#xff08;全市&#xff09; 1、时间范围&#xff1a;2000-2019年 2、范围&#xff1a;包括280多个地级市 3、来源&#xff1a;城市NJ 4、统计口径&#xff1a;全市 5、单位&#xff1a;万人 6、缺失情况&#xff1a;与城市年鉴缺失情况…

python学习笔记20230611

python语言的特点 python是脚本语言&#xff0c; 采用解释方式执行。 解释是将源代码逐条转换成目标代码同时逐条运行目标代码的过程。执行解释的计算机程序就是解释器。 解释执行方式是逐条运行用户编写的代码&#xff0c;执行性能略低&#xff0c;但他支持跨硬件或操作系统…

HNU计算机图形学-作业二

HNU计算机图形学-作业二 作业二&#xff1a;纹理和照明前言介绍实施详细信息任务1&#xff1a;加载复杂对象任务2&#xff1a;纹理映射和照明任务3&#xff1a;互动活动和动画额外任务&#xff1a;增强场景的视觉效果&#xff08;最高20%&#xff09; 最终实现效果 作业二&…

【Protobuf速成指南】oneof关键字的使用

文章目录 2.3 oneof 字段一、基本认识二、 3.2 oneof相关函数三、Contact2.3 改写 2.3 oneof 字段 本系列文章将通过对通讯录项目的不断完善&#xff0c;带大家由浅入深的学习Protobuf的使用。这是Contacts的2.3版本&#xff0c;在这篇文章中将带大家学习Protobuf的 oneof 语关…

LVS负载均衡集群-NAT模式

目录 前言一、企业群集应用概述1. 群集的含义1.1 群集的特点1.2 扩展服务器的方式 2. 群集的类型2.1 负载均衡群集&#xff08;Load Balance Cluster&#xff09;2.2 高可用群集&#xff08;High Availability Cluster&#xff09;2.3 高性能运算群集&#xff08;High Performa…