leetcode212. 单词搜索 II

字典树+剪枝。这里的剪枝其实就是如果words里面的单词都找到了,那么就不需要再找了。
具体做法就是对于一条路径,我们如果到达了叶子节点就说明这条路径上的所有单词都已经加入答案了
这样在回溯回的时候可以删除这条路径没有分支的节点了

class Trie(object):
    def __init__(self):
        self.children = {}
        self.word = ""
class Solution(object):
    def findWords(self, board, words):
        """
        :type board: List[List[str]]
        :type words: List[str]
        :rtype: List[str]
        """
        root = Trie()
        for word in words:
            node = root
            for ch in word:
                if ch not in node.children:
                    node.children[ch] = Trie()
                node = node.children[ch]
            node.word = word

        def dfs(r,c,node):
            if board[r][c] not in node.children:
                return 
            ch = board[r][c]
            nxt = node.children[ch]
            if nxt.word:
                ans.append(nxt.word)
                nxt.word = ""
            if nxt.children:
                board[r][c] = "#"
                for nr,nc in [(r+1,c),(r-1,c),(r,c+1),(r,c-1)]:
                    if 0 <= nr < row and 0 <= nc < col:
                        dfs(nr,nc,nxt)
                board[r][c] = ch      #四个方向都不行再回溯
            if not nxt.children:
                node.children.pop(ch)

        ans = []
        row,col = len(board),len(board[0])
        for r in range(row):
            for c in range(col):
                dfs(r,c,root)
        return ans

前缀树加回溯,前缀树的作用是把单词放到树上,这样就不需要对每个word进行查询,遍历字符矩阵每个元素当作开头看是否能匹配就可以了

class Trie(object):
    def __init__(self):
        self.children = {}
        self.word = ""
class Solution(object):
    def findWords(self, board, words):
        """
        :type board: List[List[str]]
        :type words: List[str]
        :rtype: List[str]
        """
        root = Trie()
        for word in words:
            node = root
            for ch in word:
                if ch not in node.children:
                    node.children[ch] = Trie()
                node = node.children[ch]
            node.word = word

        def dfs(r,c,node):
            if board[r][c] not in node.children:
                return
            ch = board[r][c]
            node = node.children[ch]
            if node.word != "":
                ans.add(node.word)
            board[r][c] = "#"
            for nr, nc in [(r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)]:
                if 0 <= nr < m and 0 <= nc < n:
                    dfs(nr, nc, node)
            board[r][c] = ch
        ans = set()
        m,n = len(board),len(board[0])
        for r in range(m):
            for c in range(n):
                dfs(r,c,root)
        return list(ans)

暴力,超时。思路对于每个单词都进入字符矩阵搜索一遍

class Solution(object):
    def findWords(self,board, words):
        sol, res = [], set()
        row = len(board)
        col = len(board[0])
        mark = [[0]*col for _ in range(row)]
        board_count = collections.defaultdict(int)
        for i in range(row):
            for j in range(col):
                board_count[board[i][j]] += 1
        def backtrack(r, c, begin):
            if len(word) == begin:
                res.add("".join(sol[:]))
                return
            if begin > 10:
                return
            for nr, nc in [(r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)]:
                if 0 <= nr < row and 0 <= nc < col and mark[nr][nc] == 0 and board[nr][nc] == word[begin]:
                    mark[nr][nc] = 1
                    sol.append(word[begin])
                    backtrack(nr, nc, begin + 1)
                    mark[nr][nc] = 0
                    sol.pop()
        def helper(word, board_count):
            count = Counter(word)
            for char in word:
                if count[char] > board_count[char]:
                    return False
            return True
        for word in words:
            if helper(word, board_count):
                for i in range(row):
                    for j in range(col):
                        if word[0] == board[i][j]:
                            mark[i][j] = 1
                            sol.append(word[0])
                            backtrack(i,j,1)
                            mark[i][j] = 0
                            sol.pop()
        return list(res)

你可能感兴趣的:(字典树Trie,DFS,深度优先,算法)