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
矩阵中查找,返回 []

挑战

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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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的解法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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])

 

posted @   bonelee  阅读(547)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
历史上的今天:
2018-10-25 keras-anomaly-detection 代码分析——本质上就是SAE、LSTM时间序列预测
2018-10-25 VAE demo
2018-10-25 AIOps探索:基于VAE模型的周期性KPI异常检测方法——VAE异常检测
2018-10-25 杜伦大学提出GANomaly:无需负例样本实现异常检测
2018-10-25 基于PU-Learning的恶意URL检测——半监督学习的思路来进行正例和无标记样本学习
2018-10-25 异常检测——局部异常因子(Local Outlier Factor ,LOF)算法
2017-10-25 通过DNS通道传输的交互式PowerShell脚本
点击右上角即可分享
微信分享提示