212. 单词搜索 II (DFS Trie )

 

难度困难

给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words, 返回所有二维网格上的单词 。

单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

 

示例 1:

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

示例 2:

输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]
 
from collections import defaultdict
class Trie:
    def __init__(self):
        self.children = defaultdict(Trie)
        self.is_end = False
        self.word = ""

    def insert(self,word):
        node = self
        for ch in word:
            node = node.children[ch]
        node.is_end = True
        node.word = word
        #print(node.word)
    

class Solution:
    def __init__(self):
        self.res = []
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        def dfs(board,i,j,root):
            if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]):
                return
            if root == None:
                return
            ch = board[i][j] 
           
            if ch not in root.children:
                return
            if root.children[ch].is_end:
                self.res.append(root.children[ch].word)
            
            if not root.children[ch].children:
                return
            board[i][j] = "#"
            for ij in [[i+1,j],[i-1,j],[i,j+1],[i,j-1]]:
                dfs(board,ij[0],ij[1],root.children[ch])
            board[i][j] = ch
      
        root = Trie()
        for word in words:
            root.insert(word)

        for i in range(len(board)):
            for j in range(len(board[0])):
                path = []
                dfs(board,i,j,root)
        return list(set(self.res))

 

 
 
 
from collections import defaultdict
class Trie:
    def __init__(self):
        self.children = defaultdict(Trie)
        self.is_end = False
        self.word = ""

    def insert(self,word):
        node = self
        for ch in word:
            node = node.children[ch]
        node.is_end = True
        node.word = word
    

class Solution:
    def __init__(self):
        self.root = Trie()
        self.res = set()


    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        def dfs(board,i,j,root):
            if root == None:
                return
            if i < 0 or j < 0 or i >= len(board) or j >= len(board[0]):
                return
            ch = board[i][j]
            if ch =='#' or  ch not in root.children:
                return
            node = root.children[ch]
            if node.is_end:
                self.res.add(node.word)
            
            #剪枝,不然会超时
            if not node.children:
                return
            
            board[i][j] = '#'
            for i2, j2 in [(i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)]:
                dfs(board,i2,j2,node)
            board[i][j] = ch

        for word in words:
            self.root.insert(word)
        for i in range(len(board)):
            for j in range(len(board[0])):
                dfs(board,i,j,self.root)
        return list(self.res)

 

 
 
 
       

 

 
 
struct TrieNode {
    bool is_end;
    string word;
    vector<TrieNode*> children;
    TrieNode() {
        this->is_end = false;
        this->children = vector<TrieNode*>(26);
    }
};

class Solution {
    TrieNode*  root = new TrieNode();
    unordered_set<string> final_set;
    vector<vector<int>> dirs = {{0,1},{0,-1},{1,0},{-1,0}};
public:
    void insert(string word) {
        TrieNode* node = this->root;
        for(auto ch :word) {
            if (node->children[ch-'a'] == nullptr) {
                node->children[ch-'a'] = new TrieNode();
            }
            node = node->children[ch-'a'];
        }
        node->is_end = true;
        node->word = word;
    }
    void deleteWordFromTrie(string word) {
        root = remove(root, word, 0);
    }

    TrieNode* remove(TrieNode* node, string key, int i) {
    if (node == nullptr) {
        return nullptr;
    }
    if (i == key.size()) {
        // 找到了 key 对应的 TrieNode,删除 val
        node->is_end = false;
    } else {
        // 递归去子树进行删除
        node->children[key[i]-'a'] = remove(node->children[key[i]-'a'], key, i + 1);
    }
    // 后序位置,递归路径上的节点可能需要被清理
    if (node->is_end != false) {
        // 如果该 TireNode 存储着 val,不需要被清理
        return node;
    }
    // 检查该 TrieNode 是否还有后缀
    for (int c = 0; c < 26; c++) {
        if (node->children[c] != nullptr) {
            // 只要存在一个子节点(后缀树枝),就不需要被清理
            return node;
        }
    }
    // 既没有存储 val,也没有后缀树枝,则该节点需要被清理
    return nullptr;
}


    void dfs(vector<vector<char>>& board,vector<vector<bool>>& visited, TrieNode* node,string& path, int i, int j) {
        if (i < 0 || j < 0 || i >=board.size() || j >= board[0].size() || visited[i][j]) {
            return;
        }
       
        auto ch = board[i][j];
        if (node == nullptr || node->children[ch-'a'] == nullptr) {
            return;
        }
        path+=ch;
        visited[i][j] = true;
        if (node->children[ch-'a']->is_end) {
            final_set.insert(path);
            deleteWordFromTrie(path);
        }
        for( auto dir :dirs) {
            int new_i = i + dir[0];
            int new_j = j + dir[1];
            dfs(board,visited,node->children[ch-'a'],path,new_i,new_j);                    
        }
        path.pop_back();
        visited[i][j] = false;
    
    }

    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        for(auto word : words) {
            insert(word);
        }
        string path = "";
        vector<vector<bool>> visited = 
        vector<vector<bool>>(board.size(),vector<bool>(board[0].size(),false));
        for (int i = 0; i < board.size();i++) {
            for (int j = 0; j < board[0].size();j++) {
                dfs(board,visited, root,path,i,j);
            }
        }
        vector<string> final_res;
        for(auto w : final_set) {
            final_res.emplace_back(w);
        }
        return final_res;
    }
};

 

posted @ 2022-06-04 17:23  乐乐章  阅读(31)  评论(0编辑  收藏  举报