LeetCode:212 单词搜索Ⅱ

这道题是DFS+前缀树,是一道标准的模板题

这里面的Tire类的定义写的方法与之前的 208 略有不同,但基本上一样。只是单独定义了一下TireNode节点类。

//定义节点,类/结构体
class TireNode {
public:
    TireNode(){
    }
    bool isEnd = false;
    vector<TireNode*> next = vector<TireNode*> (26, nullptr);
};

class Tire {
public:
    TireNode* root = new TireNode(); // 建立根节点
    Tire() {
    }

    void insert(string s) {
        TireNode* node = root;
        for(char ch : s) {
            if(node->next[ch-'a'] == nullptr) {
                node->next[ch-'a'] = new TireNode();
            }
            node = node->next[ch-'a'];
        }
        node->isEnd = true;
    }

    bool search(string s) {
        TireNode* node = root;
        for(char ch : s) {
            node = node->next[ch-'a'];
            if(node == nullptr) {
                return false;
            }
        }
        return node->isEnd;
    }

    bool isPrefix(string s) {
        TireNode* node = root;
        for(char ch : s) {
            node = node->next[ch-'a'];
            if(node == nullptr) {
                return false;
            }
        }
        return true;
    }
};

class Solution {
public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        //第一步,用字典树来存储字典列表中的所有字符串
        Tire tire;
        for(string s : words) {
            tire.insert(s);
        }
        set<string> ans; //定义set作为装结果的容器,防止重复
        //对二维网格的每一个点都进行四个方向的深度优先遍历
        for(int i = 0; i < board.size(); i++) {
            for(int j = 0; j < board[i].size(); j++) {
                string cur = ""; 
                cur += board[i][j];
                board[i][j] -= 26;
                DFS(board, tire, ans, cur, i, j);
                board[i][j] += 26;
            }
        }

        vector<string> res;
        for(string s : ans) {
            res.push_back(s);
        }
        return res;
    }

    void DFS(vector<vector<char>>& board, Tire& tire, set<string>& res, string& cur, int x, int y) {
        if(!tire.isPrefix(cur)) { //当前的字符串不在前缀树中,直接返回
            return;
        }
        if(tire.search(cur)) { //当前字符串是前缀树中的一个单词,直接加入结果中
            res.insert(cur);
        }
        //当前字符串是前缀树中的一个前缀,依次向4个方向进行DFS的探索
        if(x-1 >= 0 && board[x-1][y] >= 'a') {
            cur += board[x-1][y];
            board[x-1][y] -= 26; //将加入字符串的那个字符减去'a'防止这次再访问
            DFS(board, tire, res, cur, x-1, y); //继续递归
            board[x-1][y] += 26; //这次递归完返回之后要将字符恢复,用于下次查找
            cur = cur.substr(0, cur.size()-1); //去掉最后一个字符
        }
        if(y-1 >= 0 && board[x][y-1] >= 'a') {
            cur += board[x][y-1];
            board[x][y-1] -= 26; //将加入字符串的那个字符减去'a'防止这次再访问
            DFS(board, tire, res, cur, x, y-1); //继续递归          
            board[x][y-1] += 26; //这次递归完返回之后要将字符恢复,用于下次查找
            cur = cur.substr(0, cur.size()-1); //去掉最后一个字符
        }
        if(x+1 < board.size() && board[x+1][y] >= 'a') {
            cur += board[x+1][y];
            board[x+1][y] -= 26; //将加入字符串的那个字符减去'a'防止这次再访问
            DFS(board, tire, res, cur, x+1, y); //继续递归           
            board[x+1][y] += 26; //这次递归完返回之后要将字符恢复,用于下次查找
            cur = cur.substr(0, cur.size()-1); //去掉最后一个字符
        }
        if(y+1 < board[0].size() && board[x][y+1] >= 'a') {   //bug:x,y轴方向不是任意的,需要和主函数中for循环的i,j的范围对应,因此x是纵轴
            cur += board[x][y+1];
            board[x][y+1] -= 26; //将加入字符串的那个字符减去'a'防止这次再访问
            DFS(board, tire, res, cur, x, y+1); //继续递归           
            board[x][y+1] += 26; //这次递归完返回之后要将字符恢复,用于下次查找
            cur = cur.substr(0, cur.size()-1); //去掉最后一个字符
        }
    }
};
发布了97 篇原创文章 · 获赞 11 · 访问量 2458

猜你喜欢

转载自blog.csdn.net/chengda321/article/details/104393155