212 - Word Search II

2020/07/01

leetcode

Problem

Given a 2D board and a list of words from the dictionary, find all words in the board.

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

Example:

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"]


Note:

All inputs are consist of lowercase letters a-z.
The values of words are distinct.

Solution

DFS the matrix.

To break the dfs earlier, a Trie data structure is introduced to check wether the path is a valid combination

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

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        node = self.root
        for w in word:
            node = node.children[w]
        node.isWord = True

class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        trie = Trie()
        node = trie.root
        for w in words:
            trie.insert(w)
        ans = []
        for i in range(len(board)):
            for j in range(len(board[0])):
                self.dfs(board, i, j, node, "", ans)
        return ans


    def dfs(self, board, i, j, node, path, ans):
        if node.isWord:
            ans.append(path)
            node.isWord = False

        if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or board[i][j] not in node.children:
            return

        val = board[i][j]
        board[i][j] = "#"
        for pair in [[0, 1], [1, 0], [0, -1], [-1, 0]]:
            self.dfs(board, i+pair[0], j+pair[1], node.children[val], path+val, ans)
        board[i][j] = val