leetcode 212:单词搜索II

leetcode: 212. 单词搜索II 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。, 返回所有二维网格上的单词。来源:力扣(LeetCode)单词必须按照字母顺序,通过。和一个单词(字符串)列表。 阅读详情

题目描述:
给定一个 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”]
输出:[]
思路:
相当于在原来79问题的基础上,变成了检查一串字符串,为了避免重复的遍历board,将所给出的words构建一个字典树,然后从board的第一个字母开始,按照移动方式是否会在字典树中,这里用到一个技巧就是利用两个数组
self.dx = [-1, +1, 0, 0] # 用来控制上下左右
self.dy = [0, 0, -1, +1]

class Solution:
    def __init__(self):
        self.root = {}
        self.end = '#'
        self.dx = [-1, +1, 0, 0]  # 用来控制上下左右
        self.dy = [0, 0, -1, +1]

    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        # 以候选池中的单词构成一个字典树,然后从board的每一个元素开始搜索,要是有在trie上的就加入到结果中
        if len(board) == 0 and len(board[0]) == 0:
            return []
        if len(words) == 0:
            return []
        self.result = []
        # 利用候选池中的单词构成一个字典树
        for i in range(len(words)):
            self.insert(words[i])

        # 进行查找满足的,注意需要进行判重,所以需要一个额外的数组
        visited = []
        for a in range(len(board)):
            visited.append([])
            for b in range(len(board[0])):
                visited[a].append(0)  # 0表示没有访问过

        # 查找
        for i in range(len(board)):
            for j in range(len(board[0])):
                if board[i][j] in self.root.keys():
                    self.dfs(i, j, board, visited, "", self.root)
        # 将self.result进行字典序排序
        # self.result.sort()
        self.res = []
        for i in range(len(self.result)):
            if self.result[i] not in self.res:
                self.res.append(self.result[i])
        return self.res


    def insert(self, word):
        if not word:
            return
        node = self.root
        for char in word:
            if char in node.keys():
                node = node[char]
            else:
                node[char] = {}
                node = node[char]
        node[self.end] = self.end

    def dfs(self, i, j, board, visited, cur_words, cur_dict):
        cur_words = cur_words + board[i][j]
        visited[i][j] = 1
        cur_dict = cur_dict[board[i][j]]
        # print(cur_dict)
        if self.end in cur_dict:
            self.result.append(cur_words)
        for yi in range(4):
            x = i + self.dx[yi]
            y = j + self.dy[yi]
            if 0 <= x < len(board) and 0 <= y < len(board[0]) and \
                    visited[x][y] != 1 and board[x][y] in cur_dict:
                self.dfs(x, y, board, visited, cur_words, cur_dict)
        visited[i][j] = 0

官方的方法:
(一)与上述的整体思路是一致的,只是实现的方式不一样。
根据题意,我们需要逐个遍历二维网格中的每一个单元格;然后搜索从该单元格出发的所有路径,找到其中对应 \textit{words}words 中的单词的路径。因为这是一个回溯的过程,所以我们有如下算法:

遍历二维网格中的所有单元格。

深度优先搜索所有从当前正在遍历的单元格出发的、由相邻且不重复的单元格组成的路径。因为题目要求同一个单元格内的字母在一个单词中不能被重复使用;所以我们在深度优先搜索的过程中,每经过一个单元格,都将该单元格的字母临时修改为特殊字符(例如 #),以避免再次经过该单元格。

如果当前路径是words 中的单词,则将其添加到结果集中。如果当前路径是 words 中任意一个单词的前缀,则继续搜索;反之,如果当前路径不是 words 中任意一个单词的前缀,则剪枝。我们可以将words 中的所有字符串先添加到前缀树中,而后用 O(|S|)O(∣S∣) 的时间复杂度查询当前路径是否为words 中任意一个单词的前缀。

在具体实现中,我们需要注意如下情况:

因为同一个单词可能在多个不同的路径中出现,所以我们需要使用哈希集合对结果集去重。

在回溯的过程中,我们不需要每一步都判断完整的当前路径是否是 words 中任意一个单词的前缀;而是可以记录下路径中每个单元格所对应的前缀树结点,每次只需要判断新增单元格的字母是否是上一个单元格对应前缀树结点的子结点即可。

from collections import defaultdict


class Trie:
    def __init__(self):
        self.children = defaultdict(Trie)
        self.word = ""

    def insert(self, word):
        cur = self
        for c in word:
            cur = cur.children[c]
        cur.is_word = True
        cur.word = word


class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        trie = Trie()
        for word in words:
            trie.insert(word)

        def dfs(now, i1, j1):
            if board[i1][j1] not in now.children:
                return

            ch = board[i1][j1]

            now = now.children[ch]
            if now.word != "":
                ans.add(now.word)

            board[i1][j1] = "#"
            for i2, j2 in [(i1 + 1, j1), (i1 - 1, j1), (i1, j1 + 1), (i1, j1 - 1)]:
                if 0 <= i2 < m and 0 <= j2 < n:
                    dfs(now, i2, j2)
            board[i1][j1] = ch

        ans = set()
        m, n = len(board), len(board[0])

        for i in range(m):
            for j in range(n):
                dfs(trie, i, j)

        return list(ans)

(二)当我们使用方法一来找出所有同时在二维网格和单词列表中出现的单词时,我们需要遍历每一个单元格的所有路径,会找到大量重复的单词。

为了缓解这种情况,我们可以将匹配到的单词从前缀树中移除,来避免重复寻找相同的单词。因为这种方法可以保证每个单词只能被匹配一次;所以我们也不需要再对结果集去重了。

from collections import defaultdict


class Trie:
    def __init__(self):
        self.children = defaultdict(Trie)
        self.word = ""

    def insert(self, word):
        cur = self
        for c in word:
            cur = cur.children[c]
        cur.is_word = True
        cur.word = word


class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        trie = Trie()
        for word in words:
            trie.insert(word)
		
        def dfs(now, i1, j1):
            if board[i1][j1] not in now.children:
                return

            ch = board[i1][j1]

            nxt = now.children[ch]
            if nxt.word != "":
                ans.append(nxt.word)
                nxt.word = ""

            if nxt.children:
                board[i1][j1] = "#"
                for i2, j2 in [(i1 + 1, j1), (i1 - 1, j1), (i1, j1 + 1), (i1, j1 - 1)]:
                    if 0 <= i2 < m and 0 <= j2 < n:
                        dfs(nxt, i2, j2)
                board[i1][j1] = ch

            if not nxt.children:
                now.children.pop(ch)

        ans = []
        m, n = len(board), len(board[0])

        for i in range(m):
            for j in range(n):
                dfs(trie, i, j)

        return ans

复杂度分析

时间复杂度:O(m×n×3^
l−1),其中 mm 是二维网格的高度,n 是二维网格的宽度,l是最长单词的长度。我们仍需要遍历 m×n 个单元格,每个单元格在最坏情况下仍需要遍历4×3 ^l−1条路径。
空间复杂度:O(k×l),其中 k 是 words 的长度,l 是最长单词的长度。最坏情况下,我们需要 O(k×l) 用于存储前缀树。

leetcode: 212.单词搜索II 题目 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/word-search-ii 给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。 单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。 示例 1: 输入:board = [[“o”,“a”,“a”,“n”],[“e 阅读详情

相关推荐

深入解析TI C2000 ePWM模块:峰值电流模式Buck与LLC谐振变换器实战配置

脉宽调制(PWM)技术是电力电子与数字电源控制的核心,它通过调节开关信号的占空比或频率,实现对功率变换器输出电压、电流的精确控制。其基本原理是利用微控制器内部的定时器和比较器,生成具有特定时序的方波信号,驱动功率开关器件。这项技术的核心价值在于将复杂的模拟控制环路数字化,从而提升系统的可控性、灵活性和可靠性。在电机驱动、不间断电源(UPS)、服务器电源和新能源逆变器等广泛应用场景中,PWM技术都是实现高效能量转换的基石。本文聚焦于德州仪器(TI)C2000系列微控制器中功能强大的增强型PWM(ePWM)模块

weixin_30410119的博客 345

单词搜索-c语言

单词搜索 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 代码解题如下: int pi,pj; //static int r[100][100]; void f(char** board,int n ,int m,int x,int y,char * wo

weixin_43327597的博客 1183

模型优化系列——模型剪枝/量化概述

模型优化目的:通过减少模型大小,提高推理速度等使模型成功部署在各个硬件中并实时有效运作。

qq_61210574的博客 1293

79. 单词搜索

79. 单词搜索 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

weixin_43412762的博客 898

maya中的几个热盒(空格、shift、w键)

maya中许多功能打包放进了不同的热盒中,让我们使用起来更加的便捷,熟练掌握后可以大大提升了建模速度。按下不同按键后鼠标不需要精确点到某个图标,往某个方向滑滑滑就打开了相应功能,非常的炫酷和迅猛。

m0_71983242的博客 1756

组合预测模型 | LSTM-XGBoost长短期记忆神经网络结合极限梯度提升树时间序列预测(Matlab程序)

组合预测模型 | LSTM-XGBoost长短期记忆神经网络结合极限梯度提升树时间序列预测(Matlab完整程序)

前程算法屋的博客 2180

力扣每日一题79:单词搜索

给定一个m x n二维字符网格board和一个字符串单词word。如果word存在于网格中,返回true;否则,返回false。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。truetruefalseword你可以使用搜索剪枝的技术来优化解决方案,使其在board更大的情况下可以更快解决问题?通过次数462.9K提交次数997.8K通过率46.4%

m0_73441691的博客 785

基于YOLOv10的建筑图纸物体检测系统:从数据集构建到UI界面实现

高度结构化的图形元素标准化的符号和标注系统多层次的细节表达精确的尺寸和位置关系。

YOLO 390

【力扣】79. 单词搜索

题目: 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 示例 1: 输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED” 输出:true 示例 2

漆黑梦工厂 4492

【从零开始学习 UVM】1.2、UVM 概述 —— UVM Installation(UVM 安装)

【从零开始学习 UVM】1.2、UVM 概述 —— UVM Installation(UVM 安装)

努力,加油每一天鸭~ 1944

【深度学习新浪潮】如何上手DINO v3:Meta新一代视觉大模型实战指南

自定义数据集类(适配本地/公开数据集)# 去除batch维度# 构建数据加载器# 定义分类模型(冻结预训练层,仅训练分类头)self.classifier = nn.Linear(dino_model.config.hidden_size, num_classes) # 分类头global_feat = outputs.global_attention_pool # 取全局特征# 初始化模型# 冻结预训练层(仅训练分类头)# 定义损失函数和优化器。

专注:太空算力、AI infra、异构调度、大模型成本工程 491

LeetCode 212: 单词搜索 II

目录LeetCode 212: 单词搜索 II题目描述解题 LeetCode 212: 单词搜索 II 题目描述 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。 示例: 输入: words = [“oath”,“pea”,“eat”,“rain”] and board = [ [‘o’,‘a

s_Shune 177

麻雀搜索算法(SSA)详解:从鸟群智能到优化实践

麻雀搜索算法(SSA)是一种新型群智能优化算法,模拟麻雀群体的觅食行为和反捕食机制。该算法将优化问题转化为麻雀群体对食物源的搜索过程,通过发现者、加入者和警戒者的角色分工实现高效优化。SSA具有原理新颖、参数合理、收敛快速等特点,在函数优化、工程设计和机器学习等领域展现出良好应用前景。算法通过数学模型模拟麻雀的觅食策略,包括发现者全局探索、加入者局部开发和警戒者危险预警机制,有效平衡了全局搜索与局部开发能力。SSA相比传统优化算法具有更好的收敛性和优化效果。

qq_42212808的博客 1072

leetcode-212:单词搜索 II

优化一。

菊头蝙蝠的博客 447

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【中等】力扣算法题解析LeetCode212:单词搜索 II

题目要求在二维字符网格中查找给定单词列表中的所有单词,单词需由相邻单元格字母构成。采用字典树(Trie)存储单词,结合DFS回溯搜索:1)构建字典树;2)遍历网格每个起点,DFS匹配字典树路径;3)剪枝优化(无匹配提前终止、移除已匹配单词);4)结果去重后排序输出。Java代码通过TrieNode类实现字典树,DFS中使用原地标记访问状态,回溯恢复字符。

ylumwd的博客 1012

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

LeetCode 212:单词搜索 II

在中,找出所有能通过构成的单词(单词来自给定列表,每个单元格只能用一次)。

m0_75126572的博客 961

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

力扣212题:单词搜索 II

本文详细解读了力扣第212题“单词搜索 II”,通过使用回溯法和 Trie 树高效地解决了这一问题,并提供了详细的解释和模拟面试问答。希望读者通过本文的学习,能够在力扣刷题的过程中更加得心应手。

10年数据\经营分析经验,现任大厂数据分析负责人 354

力扣:212. 单词搜索 II

目录题目:494. 目标和示例1示例2提示:解题思路 题目:494. 目标和 难度: 困难 题目: 给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。 单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。 来源:力扣(LeetCode) 链接: 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 示例1

aruewds的博客 277

LeetCode 212题解析:Trie树优化单词搜索II算法

Trie树(前缀树)是一种高效处理字符串集合的数据结构,特别适合解决具有公共前缀的字符串搜索问题。其核心原理是通过共享公共前缀来减少存储空间和搜索时间,将时间复杂度从O(K×L)优化到O(L)。在算法题如LeetCode 212单词搜索II中,Trie树结合回溯算法能有效解决二维网格中的多单词搜索问题,避免暴力搜索的冗余计算。典型应用场景包括搜索引擎自动补全、拼写检查等文本处理系统。本文以单词搜索II为例,详解如何通过Trie树实现DFS剪枝优化,并分析时间复杂度和工程实践中的内存优化策略。

weixin_34101914的博客 245

【LeetCode: 212. 单词搜索 II - dfs】

【LeetCode: 212. 单词搜索 II - dfs】给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words, 返回所有二维网格上的单词 。 单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

Coder_ljw的博客 1300

leetcode:212. 单词搜索 II

代码】leetcode:212. 单词搜索 II。

OceanStar的博客 252

Leetcode 212:单词搜索 II(超详细的解法!!!)

给定一个二维网格board和一个字典中的单词列表words,找出所有同时在二维网格和字典中出现的单词。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。 示例: 输入: words = ["oath","pea","eat","rain"] and board = [ ['o','a',...

coordinate的博客 908

LeetCode 第212题:单词搜索 II

Trie树构建:我们使用Trie树来存储所有需要查找的单词,这样可以高效地进行前缀匹配。深度优先搜索(DFS):在二维网格中,从每个字符开始进行DFS,以查找可能的单词。标记访问:在DFS过程中,将已经访问过的字符标记为特殊符号(如),以避免重复使用。方向搜索:对每个字符进行上下左右四个方向的递归搜索,探索所有可能的路径。结果去重:如果在DFS过程中找到一个完整的单词,将其加入结果列表,并在Trie树中标记为已找到,以防重复加入。恢复状态:在DFS结束后,恢复网格中字符的原始状态,以便其他路径的搜索。

byteinit的专栏 423

​LeetCode刷题实战212:单词搜索 II

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !...

程序IT圈 140

LeetCode 212. 单词搜索 II:Trie+DFS 高效解法

本文详细解析了LeetCode 212题"单词搜索II"的解题思路与实现方法。该题结合前缀树(Trie)和深度优先搜索(DFS)两种算法,要求在一个字符矩阵中搜索多个单词。文章首先分析题目要求,指出朴素解法效率低下的问题;然后介绍使用Trie树合并公共前缀的优化思路,并给出完整代码实现,包括Trie结构定义、DFS搜索逻辑和回溯处理;最后分析算法复杂度,并指出常见错误和优化方向。通过Trie树剪枝和DFS回溯,该解法能有效提升搜索效率,时间复杂度为O(mn3^L)。

2401_86788218的博客 437
上一篇: leetcode 79: 单词搜索
下一篇: leetcode 191: 位1的个数
coding_diamond
博客等级 码龄8年 8粉丝 131原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值