leetcode刷题笔记 212题 单词搜索 II
leetcode刷题笔记 212题 单词搜索 II
源地址:212. 单词搜索 II
问题描述:
给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例:
输入:
words = ["oath","pea","eat","rain"] and board =
[
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]输出: ["eat","oath"]
说明:
你可以假设所有输入都由小写字母 a-z 组成。提示:
你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)。
//本题基于208题与211题实现Trie
//为了方便,将isWordEnd由判断是否结尾改为在每个单词的最后一个字符的节点储存单词,方便在回溯过程中添加
import scala.collection.mutable
//节点定义,默认其存储“”
class Node (val children: Array[Node], var isWordEnd: String = "")
//定义Trie
class Trie {
val root = new Node(new Array[Node](26), "")
//利用word构建Trie树
def addWord(word: String): Unit = {
var ptr = root
for (ch <- word) {
if (ptr.children(ch - 'a') == null) ptr.children(ch - 'a') = new Node(new Array[Node](26), "")
ptr = ptr.children(ch - 'a')
}
ptr.isWordEnd = word
}
}
object Solution {
//对于数组构造Trie
def buildTrie(words: Array[String]): Trie = {
val root = new Trie()
for (word <- words) {
root.addWord(word)
}
return root
}
def findWords(board: Array[Array[Char]], words: Array[String]): List[String] = {
val trie = buildTrie(words)
val rowLength = board.length
val colLength = board.head.length
var res = Set.empty[String]
//判断位置是否正确
def inBounds(coord: (Int, Int)): Boolean = {
coord._1 >= 0 && coord._2 >= 0 && coord._1 < rowLength && coord._2 < colLength
}
//访问合理的四周位置
def getNeighbors(coord: (Int, Int)): List[(Int, Int)] = {
List(
(coord._1 + 1, coord._2),
(coord._1 - 1, coord._2),
(coord._1, coord._2 + 1),
(coord._1, coord._2 - 1)
).filter(inBounds(_))
}
//遍历查找
def checkMatches(node: Node, coord: (Int, Int)): Unit = {
val ch = board(coord._1)(coord._2)
//已经访问过 返回
if (ch == '#') return
//当前字符的节点存在
if (node.children(ch - 'a') != null){
val ptr = node.children(ch - 'a')
//到达单词末尾
if (ptr.isWordEnd != ""){
res += ptr.isWordEnd
}
//标记已访问
board(coord._1)(coord._2) = '#'
//访问四周
for (neighbor <- getNeighbors(coord)) {
val letter = board(coord._1)(coord._2)
checkMatches(ptr, neighbor)
}
//回溯
board(coord._1)(coord._2) = ch
}
}
for (i <- 0 until rowLength; j <- 0 until colLength){
checkMatches(trie.root, (i, j))
}
return res.toList
}
}