212. Word Search II:多个单词查找
写在前面:这两周持续看花花酱整理的题目列表和视频讲解,也得益于自己持续多年刷题,今天刷这道题目的想法是:会trie树居然就能攻克hard题目!我也离独立攻破hard题目不远了嘛。前段时间看王争在极客时间的系列课程,trie树是不在话下的。好,开始写题。
目录
- 题目描述
- 暴力回溯
- Trie树
题目描述
输入:二维字符数组,做棋盘baord;字符串列表words。
返回:可以在棋盘中找到的所有单词word。
规则:每个单词需要按顺序在棋盘中匹配,棋盘匹配的时候只能移动相邻位置。相邻位置是指上下左右。
例子:输入
board = [
[‘o’,‘a’,‘a’,‘n’],
[‘e’,‘t’,‘a’,‘e’],
[‘i’,‘h’,‘k’,‘r’],
[‘i’,‘f’,‘l’,‘v’]
]
words = [“oath”,“pea”,“eat”,“rain”]
输出: [“eat”,“oath”]
暴力回溯
按照回溯法,每次解决一个单词word。可以参考题目79。
参考例子中,board的行列:m=4,n=4。查找单词word=oath。dfs搜索的时候每找到单词中的一个字符作为一层。在每一层向下一层移动过程中有上、下、左、右4种选择。
枚举每一个位置(i,j)作为起始查找位置。因为不确定哪个位置的ch与word的第一个字符相同。
dfs(i,j,index),i:第i行;j:第j列;index:单词中的第index个字符。
如果 board[i][j]=word[index],则设置board[i][j]=’#’,防止重复查找,继续向4个方向遍历。
当index=word.length的时候,表示word是存在的,加入结果集。
当数组下标i,j越界,或者重复查找的时候返回。
如果board[i][j]!=word[index],则返回,不继续搜索。
最终每个单词查找一次,返回结果。
时间复杂度:$O(m∗n∗4l)O(m*n*4^l)O(m∗n∗4l),l=单词长度
class Solution {private char[][] board;private String word;private int m;private int n;public List<String> findWords(char[][] board, String[] words) {this.board = board;m = board.length;if(m == 0) return new ArrayList<String>();n = board[0].length;List<String> result = new ArrayList<String>();for(String word : words){if(findWord(word)){result.add(word);}}return result;}private boolean findWord(String word) {this.word = word;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(dfs(i,j,0)){return true;}}}return false;}private boolean dfs(int i,int j,int index){if(index == word.length()) return true;if(i<0 || i>=m || j<0 || j>=n || board[i][j]=='#'){return false;}boolean r = false;if(board[i][j] == word.charAt(index)){char ch = board[i][j];board[i][j] = '#';r = dfs(i-1,j,index+1)|| dfs(i+1,j,index+1)|| dfs(i,j-1,index+1)|| dfs(i,j+1,index+1);board[i][j] = ch;}return r;}
}
Trie树
这里需要查找多个单词。例如word=[“baa”,“bab”,“aaab”,“aaa”,“aaaa”]。单词baa和bab有公共前缀ba,暴力回溯每次都从0开始查找,浪费时间。如果能查找到baa之后回溯一步,继续查找到bab就好了。单词aaa和aaaa,也是同样的情况。这里就需要用到Trie树。Trie树在有公共前缀子串的情况下,会极大的降低时间复杂度。Trie树学习可以参考我的博客。
上图展示了构建完成的Trie树结构。这里在每个单词结束位置添加了word表示当前字符串的值。便于记录结果。
和暴力回溯类似,遍历每一个起始位置(i,j),从根节点开始查找。
dfs(i,j,node):每次查找到一个节点,word不为空,说明找到了一个字符串,加入结果集并且word设置为null。
数组下标i,j越界,或者重复访问,则返回。
如果node.children[board[i][j]-‘a’]不为空,则继续朝4个方向搜索。否则返回。
时间复杂度:构建trie树的时间复杂度是所有单词长度和:$O(sum(l))。
搜索过程,因为有合并搜索,所以最深的深度是max(l)。在每一层会查找4个方向,所以是O(4max(l))O(4^{max(l)})O(4max(l))
所以最终时间负责度是:O(sum(l)+4max(l))O(sum(l)+4^{max(l)})O(sum(l)+4max(l))
class Solution {private char[][] board;private String word;private int m;private int n;private TrieNode root;private List<String> result;public List<String> findWords(char[][] board, String[] words) {this.board = board;m = board.length;if(m == 0) return new ArrayList<String>();n = board[0].length;result = new ArrayList<String>();buildTree(words);for(int i=0;i<m;i++){for(int j=0;j<n;j++){dfs(i,j,root);}}return result;}private void dfs(int i,int j,TrieNode node){if(node.word!=null){result.add(node.word);node.word = null;}if(i<0 || i>=m || j<0 || j>=n || board[i][j]=='#'){return;} char ch = board[i][j];if(node.children[ch-'a']==null) return;TrieNode n = node.children[ch-'a'];board[i][j] = '#';dfs(i-1,j,n);dfs(i+1,j,n);dfs(i,j-1,n);dfs(i,j+1,n);board[i][j] = ch;}private void buildTree(String[] words){root = new TrieNode('/');for(String word : words){addWord(word);}}public void addWord(String word){TrieNode p = root;for(int i=0;i<word.length();i++){int idx = word.charAt(i)-'a';if(p.children[idx]==null){p.children[idx] = new TrieNode(word.charAt(i));}p = p.children[idx];}p.end = true;p.word = word;}class TrieNode{private char data;private boolean end;private TrieNode[] children = new TrieNode[26];private String word;public TrieNode(char data){this.data = data;}public boolean isEnd(){return end;}}
}
212. Word Search II:多个单词查找相关推荐
- 【DFS + Backtracking】LeetCode 212. Word Search II
LeetCode 212. Word Search II Solution1:我的答案 暴力搜索..基于第79题的答案,真的是非常之慢啊!!! 快的方法均是基于字典树的方法,真是复杂.. class ...
- leetcode 212. Word Search II | 212. 单词搜索 II(Trie,回溯,DFS)
题目 https://leetcode.com/problems/word-search-ii/ 题解 基于前缀树实现,如果把 Trie 也看做一个特殊的图的话,就是 将两个图同时进行 dfs,就像判 ...
- [Leetcode] 212. Word Search II 解题报告
题目: Given a 2D board and a list of words from the dictionary, find all words in the board. Each word ...
- 【lintcode】树形数据结构之Maxtree, Tree iterator, remove bst node, 优先队列之动态中位数Median, 矩阵dfs之word search II,最大连
解析 max ksubarray sum: 最大和 of 连续子序列 => 最大和 of k份连续子序列 属于dp,30行代码搞定,注意一些边界. substr diff: 无queu ...
- [Swift]LeetCode212. 单词搜索 II | Word Search II
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...
- LeetCode() Word Search II
超时,用了tire也不行,需要再改. class Solution {class TrieNode { public:// Initialize your data structure here.Tr ...
- 【CODE】Unique Paths Word Search (DFS dp 字典树)
目录 62. Unique Paths 63. Unique Paths II 980. Unique Paths III 79. Word Search 212. Word Search II 字典 ...
- LeetCode 79. Word Search
原题链接在这里:https://leetcode.com/problems/word-search/ 题目: Given a 2D board and a word, find if the word ...
- 数据结构 单词查找 二分法-索引表-Hash表
问题说明: 从标准输入中读入一个英文单词及查找方式,在一个给定的英文常用单词字典文件dictionary3000.txt中查找该单词,返回查找结果(查找到返回1,否则返回0)和查找过程中单词的比较次数 ...
最新文章
- 编译android系统小结
- python集合属性方法运算_Python基础__字典、集合、运算符
- 【算法】Logistic原理
- 新冠肺炎的可视化和预测分析(附代码)
- Python--三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数...
- iptables (2) 基本配置
- python单例模式继承_Python四种实现单例模式的方法
- Python是什么?Python能干什么?一篇文章让你对Python了如指掌!!
- 一个测试新人的职业规划——三个月
- Pentium 4处理器架构/微架构/流水线 (7) - NetBurst前端详解 - 分支预测
- 火遍全网,却被广东人嫌弃!昔日“百亿网红”,快被打回原形了
- R语言使用strsplit函数按照指定的分隔符号进行数据拆分、分裂(split)、分割后的数据类型为列表
- 数据分析学习总结笔记06:T检验的原理和步骤
- react前端显示图片_react.js - 关于react引用本地静态资源图片的问题
- 关于sac的一些笔记
- php 获取header头信息并显示网址,php 获取远程网址header头信息的方法
- iOS 架构模式 - 简述 MVC, MVP, MVVM
- 2022小米运维开发笔试1
- 图灵对计算机行业的贡献论文,这届图灵奖得主究竟做了什么贡献?这篇1974年的论文给了我们答案...
- 查一下服务器的系统,如何查看服务器的操作系统