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"]
输出:[]
 
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;
    }
};

 

相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...