Skip to content

Latest commit

 

History

History
222 lines (153 loc) · 5.7 KB

0212._Word_Search_II.md

File metadata and controls

222 lines (153 loc) · 5.7 KB

212. Word Search II

难度: Hard

刷题内容

原题连接

内容描述

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: 
words = ["oath","pea","eat","rain"] and board =
[
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]

Output: ["eat","oath"]
Note:
You may assume that all inputs are consist of lowercase letters a-z.

解题方案

思路 1 - 时间复杂度: O(row * col * max_len(words))- 空间复杂度: O(row * col)******

一看到就实现了一个DFS,超时了

class Solution(object):
    def findWords(self, board, words):
        """
        :type board: List[List[str]]
        :type words: List[str]
        :rtype: List[str]
        """
        if not board or not words:
            return []
        
        self.words = set(words)
        self.max_len_word = max(len(word) for word in self.words) 
        self.res = []
        self.row = len(board)
        self.col = len(board[0]) if self.row else 0
         
        for i in range(self.row):
            for j in range(self.col):
                self.dfs(board, board[i][j], i, j, set([(i,j)]))
                
        return self.res
            
    def dfs(self, board, path, x, y, visited):
        if path in self.words:
            self.res.append(path)
            self.words.remove(path)
            self.max_len_word = max(len(word) for word in self.words) if self.words else 0

        if len(path) >= self.max_len_word:
            return

        if x - 1 >= 0 and (x-1, y) not in visited:
            self.dfs(board, path+board[x-1][y], x-1, y, visited | set([(x-1, y)]))
        if y - 1 >= 0 and (x, y-1) not in visited:
            self.dfs(board, path+board[x][y-1], x, y-1, visited | set([(x, y-1)]))
        if x + 1 <= self.row - 1 and (x+1, y) not in visited:
            self.dfs(board, path+board[x+1][y], x+1, y, visited | set([(x+1, y)]))
        if y + 1 <= self.col - 1 and (x, y+1) not in visited:
            self.dfs(board, path+board[x][y+1], x, y+1, visited | set([(x, y+1)]))

思路 2 - 时间复杂度: O(row * col * max_len(words))- 空间复杂度: O(len(words) * word_len)******

看到这种字符串搜索,要想到利用trie树, beats 29.36%

class TrieNode(object):

    def __init__(self):
        self.children = dict()
        self.isWordEnd = False

    def buildTrie(self, words):
        for word in words:
            curr = self
            for char in word:
                if char not in curr.children:
                    curr.children[char] = TrieNode()
                curr = curr.children[char]
            curr.isWordEnd = True
    
class Solution(object):
    def findWords(self, board, words):
        """
        :type board: List[List[str]]
        :type words: List[str]
        :rtype: List[str]
        """
        if not board or not words:
            return []
        
        root = TrieNode()
        root.buildTrie(words)
        self.res = set()
        self.row = len(board)
        self.col = len(board[0]) if self.row else 0
        
        def dfs(x, y, node, path):
            if node.isWordEnd:
                self.res.add(path)
            if x < 0 or x >= self.row or y < 0 or y >= self.col:
                return
            if board[x][y] in node.children:
                c = board[x][y]
                board[x][y] = '*' # backtracking
                dfs(x + 1, y, node.children[c], path + c)
                dfs(x - 1, y, node.children[c], path + c)
                dfs(x, y + 1, node.children[c], path + c)
                dfs(x, y - 1, node.children[c], path + c)
                board[x][y] = c
                
        for i in range(self.row):
            for j in range(self.col):
                dfs(i, j, root, '')
                
        return list(self.res)

思路 3 - 时间复杂度: O(row * col * max_len(words))- 空间复杂度: O(len(words) * word_len)******

看到一种更简单的trie实现模式,参考yang.zheng.904

beats 57.44%

class Solution(object):
    def findWords(self, board, words):
        """
        :type board: List[List[str]]
        :type words: List[str]
        :rtype: List[str]
        """
        if not board or not words:
            return []
        
        # build trie 
        trie = {}
        for w in words:
            t = trie
            for c in w:
                if c not in t:
                    t[c] = {}
                t = t[c]
            t['#'] = '#'
            
        self.res = set()
        self.row = len(board)
        self.col = len(board[0]) if self.row else 0
        
        def dfs(x, y, node, path):
            if '#' in node:
                self.res.add(path)
            if x < 0 or x >= self.row or y < 0 or y >= self.col:
                return
            if board[x][y] in node:
                c = board[x][y]
                board[x][y] = '*' # backtracking
                dfs(x + 1, y, node[c], path + c)
                dfs(x - 1, y, node[c], path + c)
                dfs(x, y + 1, node[c], path + c)
                dfs(x, y - 1, node[c], path + c)
                board[x][y] = c
                
        for i in range(self.row):
            for j in range(self.col):
                dfs(i, j, trie, '')
                
        return list(self.res)