【lc刷题】212 单词搜索 II (134/300)

134/300

  1. 单词搜索 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(前缀树)。
     
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/word-search-ii

思路: trie tree + dfs

1. 建词典:

大概形态就是这种 root->{o:{a:{t:{h:{}.True}}}}
【lc刷题】212 单词搜索 II (134/300)_第1张图片

2. 遍历搜索

从哪个搜就mask哪个,省的有重复的被选上
从此点的上下左右搜,如果词典里刚好有,那么词典翻页,譬如:
搜到’a’, 词典里是{a:{b:{…}}}, “a"的下面正好是"b”,那么词典就翻页到{b:{…}}

board =
[
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]
root->{o:{a:{t:{h:{}.True}}}},{p:{...}},{e:{...}},...

board[0][0] “o” #词典里有
mask [['#', 'a', 'a', 'n'], 
      ['e', 't', 'a', 'e'],#词典翻页到{a:{t:{h:{}.True}}}
      ['i', 'h', 'k', 'r'],
      ['i', 'f', 'l', 'v']] 
mask [['#', '#', 'a', 'n'],#右侧词典里有
      ['e', 't', 'a', 'e'],#词典翻页到{t:{h:{}.True}}
      ['i', 'h', 'k', 'r'],
      ['i', 'f', 'l', 'v']]
mask [['#', '#', 'a', 'n'], #下侧字典里有
      ['e', '#', 'a', 'e'],#词典翻页到{h:{}.True}
      ['i', 'h', 'k', 'r'],
      ['i', 'f', 'l', 'v']]
mask [['#', '#', 'a', 'n'],
      ['e', '#', 'a', 'e'],#下侧字典里有
      ['i', '#', 'k', 'r'],#词典翻页到{{}.True} , 添加路径“oath”
      ['i', 'f', 'l', 'v']]
恢复找过的路径
recover [['#', '#', 'a', 'n'],
         ['e', '#', 'a', 'e'],
         ['i', 'h', 'k', 'r'],
         ['i', 'f', 'l', 'v']]
recover [['#', '#', 'a', 'n'],
         ['e', 't', 'a', 'e'],
         ['i', 'h', 'k', 'r'],
         ['i', 'f', 'l', 'v']]
recover [['#', 'a', 'a', 'n'],
         ['e', 't', 'a', 'e'],
         ['i', 'h', 'k', 'r'],
         ['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
         ['e', 't', 'a', 'e'],
         ['i', 'h', 'k', 'r'],
         ['i', 'f', 'l', 'v']]
board[0][1] #词典里无
board[0][2] #词典里无
board[0][3] #词典里无
board[1][0]  "e" #词典里有
mask [['o', 'a', 'a', 'n'],
      ['#', 't', 'a', 'e'], #上下右词典里均无,左侧超界
      ['i', 'h', 'k', 'r'],
      ['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
         ['e', 't', 'a', 'e'],
         ['i', 'h', 'k', 'r'],
         ['i', 'f', 'l', 'v']]
board[1][1]#词典里无
board[1][2]#词典里无
board[1][3] #以下同理
mask [['o', 'a', 'a', 'n'],
      ['e', 't', 'a', '#'],
      ['i', 'h', 'k', 'r'],
      ['i', 'f', 'l', 'v']]
mask [['o', 'a', 'a', 'n'],
      ['e', 't', '#', '#'],
      ['i', 'h', 'k', 'r'],
      ['i', 'f', 'l', 'v']]
mask [['o', 'a', 'a', 'n'],
      ['e', '#', '#', '#'],
      ['i', 'h', 'k', 'r'],
      ['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
         ['e', 't', '#', '#'],
         ['i', 'h', 'k', 'r'],
         ['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
         ['e', 't', 'a', '#'],
         ['i', 'h', 'k', 'r'],
         ['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
         ['e', 't', 'a', 'e'],
         ['i', 'h', 'k', 'r'],
         ['i', 'f', 'l', 'v']]
board[2][0]
board[2][1]
board[2][2]
board[2][3]
mask [['o', 'a', 'a', 'n'],
      ['e', 't', 'a', 'e'],
      ['i', 'h', 'k', '#'],
      ['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
         ['e', 't', 'a', 'e'],
         ['i', 'h', 'k', 'r'],
         ['i', 'f', 'l', 'v']]
board[3][0]
board[3][1]
board[3][2]
board[3][3]

变成代码:

class Node:
    def __init__(self):
        self.next = collections.defaultdict(Node)
        self.ends = False

class TrieTree:
    def __init__(self):
        self.root = Node()
        
    def insert(self, word):
        node = self.root
        for w in word:
            node = node.next[w]
        node.ends = True
    
class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        res = []
        
        t = TrieTree()
        for word in words:
            t.insert(word)
        node = t.root
        
        def dfs(node, i, j, path):
            if node.ends:
                res.append(path)
                node.ends = False
            
            if i<0 or j<0 or i>=len(board) or j>=len(board[0]): return
            
            tmp = board[i][j]
            node = node.next.get(tmp)
            if not node: return 
            
            board[i][j] = '#'
            
            for dx, dy in [(0,1),(0,-1),(1,0),(-1,0)]:
                dfs(node, i+dx, j+dy, path+tmp)
            
            board[i][j] = tmp
       
        
        for i in range(len(board)):
            for j in range(len(board[0])):
                dfs(node, i, j, '')

        return res

在这里插入图片描述
代码非原创,仿写,credit to @大红豆小薏米

你可能感兴趣的:(Leetcode,python,刷题,dfs,trietree)