zoukankan      html  css  js  c++  java
  • dfs 解决(隐式)图搜索问题

    132. 单词搜索 II

    中文
    English

    给出一个由小写字母组成的矩阵和一个字典。找出所有同时在字典和矩阵中出现的单词。一个单词可以从矩阵中的任意位置开始,可以向左/右/上/下四个相邻方向移动。一个字母在一个单词中只能被使用一次。且字典中不存在重复单词

    样例

    样例 1:

    输入:["doaf","agai","dcan"],["dog","dad","dgdg","can","again"]
    输出:["again","can","dad","dog"]
    解释:
      d o a f
      a g a i
      d c a n
    矩阵中查找,返回 ["again","can","dad","dog"]。
    

    样例 2:

    输入:["a"],["b"]
    输出:[]
    解释:
     a
    矩阵中查找,返回 []。
    

    挑战

    使用单词查找树来实现你的算法

    DIRECTIONS = [(0, -1), (0, 1), (-1, 0), (1, 0)]
    
    class Solution:
        """
        @param board: A list of lists of character
        @param words: A list of string
        @return: A list of string
        """
        def wordSearchII(self, board, words):
            if board is None or len(board) == 0:
                return []
            
            word_set = set(words)
            prefix_set = set()
            for word in words:
                for i in range(len(word)):
                    prefix_set.add(word[:i + 1])
            
            result = set()
            for i in range(len(board)):
                for j in range(len(board[0])):
                    c = board[i][j]
                    self.search(
                        board,
                        i,
                        j,
                        board[i][j],
                        word_set,
                        prefix_set,
                        set([(i, j)]),
                        result,
                    )
                    
            return list(result)
            
        def search(self, board, x, y, word, word_set, prefix_set, visited, result):
            if word not in prefix_set:
                return
            
            if word in word_set:
                result.add(word)
            
            for delta_x, delta_y in DIRECTIONS:
                x_ = x + delta_x
                y_ = y + delta_y
                
                if not self.inside(board, x_, y_):
                    continue
                if (x_, y_) in visited:
                    continue
                
                visited.add((x_, y_))
                self.search(
                    board,
                    x_,
                    y_,
                    word + board[x_][y_],
                    word_set,
                    prefix_set,
                    visited,
                    result,
                )
                visited.remove((x_, y_))
                
        def inside(self, board, x, y):
            return 0 <= x < len(board) and 0 <= y < len(board[0])
    

     注意使用prefix hash map来剪枝。

    使用trie的解法:

    DIRECTIONS = [(0, -1), (0, 1), (-1, 0), (1, 0)]
    
    class TrieNode:    		#定义字典树的节点
        def __init__(self):
            self.children = {}
            self.is_word = False
            self.word = None
            
            
    class Trie:
        def __init__(self):
            self.root = TrieNode()
            
        def add(self, word):		#字典树插入单词
            node = self.root
            for c in word:
                if c not in node.children:
                    node.children[c] = TrieNode()   #在此节点申请节点
                node = node.children[c]     		#继续遍历
            node.is_word = True
            node.word = word        #存入单词
            
        def find(self, word):	
            node = self.root
            for c in word:
                node = node.children.get(c)
                if node is None:
                    return None
                    
            return node
            
    
    class Solution:
        """
        @param board: A list of lists of character
        @param words: A list of string
        @return: A list of string
        """
        def wordSearchII(self, board, words):
            if board is None or len(board) == 0:
                return []
                
            trie = Trie()
            for word in words:			#插入单词
                trie.add(word)
    
            result = set()
            for i in range(len(board)):				#遍历字母矩阵,将每个字母作为单词首字母开始搜索
                for j in range(len(board[0])):
                    c = board[i][j]
                    self.search(
                        board,
                        i,
                        j,
                        trie.root.children.get(c),
                        set([(i, j)]),
                        result,
                    )
                    
            return list(result)
            
        def search(self, board, x, y, node, visited, result):			#在字典树上dfs查找
            if node is None:
                return
            
            if node.is_word:
                result.add(node.word)
            
            for delta_x, delta_y in DIRECTIONS:				#向四个方向查找
                x_ = x + delta_x
                y_ = y + delta_y
                
                if not self.inside(board, x_, y_):
                    continue
                if (x_, y_) in visited:
                    continue
                
                visited.add((x_, y_))
                self.search(
                    board,
                    x_,
                    y_,
                    node.children.get(board[x_][y_]),
                    visited,
                    result,
                )
                visited.remove((x_, y_))
                
        def inside(self, board, x, y):
            return 0 <= x < len(board) and 0 <= y < len(board[0])
    
  • 相关阅读:
    强化学习 | D3QN原理及代码实现
    Airtest入门及多设备管理总结
    JS图片base64压缩
    ABP框架
    .net gof23种设计模式
    VS2013添加Socket
    VS2013用InstallShield打包winfrom项目
    .net core3.1 log4net无法写日志
    git commit 修改提交说明信息
    screen 使用总结
  • 原文地址:https://www.cnblogs.com/bonelee/p/11740956.html
Copyright © 2011-2022 走看看