1. 程式人生 > 其它 >[LeetCode] 212. Word Search II_Hard tag: Trie

[LeetCode] 212. Word Search II_Hard tag: Trie

Given anm x nboardof characters and a list of stringswords, returnall words on the board.

Each word must be constructed from letters of sequentially adjacent cells, whereadjacent cellsare horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.

Example 1:

Input: board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
Output: ["eat","oath"]

Example 2:

Input: board = [["a","b"],["c","d"]], words = ["abcb"]
Output: []

Constraints:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 12
  • board[i][j]is a lowercase English letter.
  • 1 <= words.length <= 3 * 104
  • 1 <= words[i].length <= 10
  • words[i]consists of lowercase English letters.
  • All the strings ofwordsare unique.

Ideas: 利用trie,首先利用[LeetCode] 208. Implement Trie (Prefix Tree)_Medium tag: Trie裡面的trie的structure,將words裡面的word都insert進入到trie裡面。然後利用dfs,去判斷該點是否在trie裡面,如果在的話就繼續dfs,否則不dfs,並且利用backtracking。另外有兩個點需要注意,第一,因為要避免[['a', 'b', 'a']], words: ['a'], 最後結果為['a', 'a']的情況,那麼需要在dfs中每次append path進入到ans之後設定node.isWord = False, 就不會有重複的path情況。第二,在dfs時, 先判斷node.isWord 是否為true, 不需要看i, j 為相應的range裡面, 否則會miss掉一些情況。

T: O(len(words) * len(word) + (m * n) ^ 2), S:O(len(words) * len(word))

Code

class TrieNode:
    def __init__(self):
        self.isWord = False
        self.children = dict()

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.isWord = True
        
class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        ans, trie, m, n = [], Trie(), len(board), len(board[0])
        for word in words:
            trie.insert(word)
        for i in range(m):
            for j in range(n):
                self.dfs(board, i, j, "", trie.root, ans)
        return ans
    
    def dfs(self, board, i, j, path, node, ans):
        if node.isWord:
            ans.append(path)
            node.isWord = False
        if 0 <= i < len(board) and 0 <= j < len(board[0]):
            temp = board[i][j]
            if temp not in node.children:
                return 
            node = node.children[temp]
            board[i][j] = '#'
            self.dfs(board, i + 1, j, path + temp, node, ans)
            self.dfs(board, i - 1, j, path + temp, node, ans)
            self.dfs(board, i, j + 1, path + temp, node, ans)
            self.dfs(board, i, j - 1, path + temp, node, ans)
            board[i][j] = temp