212. 单词搜索 II

要求:在矩阵相邻找字典里单词
思路:
法一:暴力,从矩阵每个点开始向四个方向找,字典单词先哈希表存起来。O(mn4^10)

class Solution {
private:
    unordered_set<string> us;
    vector<vector<char>> board;
    vector<pair<int, int>> direction;
    int rows;
    int cols;
    bool visited[12][12];
    vector<string> ans;

public:
    vector<string> findWords(vector<vector<char>>& _board, vector<string>& words) {
        board = _board;
        direction = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
        rows = board.size();
        cols = board[0].size();
        for (string word : words) {
            us.insert(word);
        }
        string path;
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                visited[r][c] = true;
                path += board[r][c];
                dfs(r, c, path);
                path = "";
                visited[r][c] = false;
            }
        }
        return ans;
    }

    void dfs(int row, int col, string& path) {
        if (path.length() > 10) return;
        if (us.count(path) == 1) {
            ans.push_back(path);
            us.erase(path);
        }
        for (pair<int, int> dir : direction) {
            int nr = row + dir.first;
            int nc = col + dir.second;
            if (0 <= nr && nr < rows && 0 <= nc && nc < cols) {
                if (!visited[nr][nc]) {
                    visited[nr][nc] = true;
                    path += board[nr][nc];
                    dfs(nr, nc, path);
                    path.erase(path.size() - 1);
                    visited[nr][nc] = false;
                }
            }
        }
    }
};

法二:字典树的作用就是有才遍历,而不是一直无脑哈希。

class Trie {
public:
    Trie* son[26];  // 存放当前字符之后的字符
    bool isWord;
    string str;
    Trie() {
        for (int i = 0; i < 26; i++) son[i] = nullptr;
        isWord = false;
        str = "";
    }
    void insert(string word) {
        Trie* root = this;     // 从头节点开始查
        for (char c : word) {  // 类似链表的遍历
            int cur = c - 'a';
            if (root->son[cur] == nullptr) root->son[cur] = new Trie();
            root = root->son[cur];
        }
        root->isWord = true;  // 在单词的结尾节点标记一下 是单词
        root->str = word;     // 结尾直接记录单词
    }
};

class Solution {
public:
    vector<vector<char>> board;
    Trie trie;
    int rows;
    int cols;
    vector<pair<int, int>> direction;
    bool visited[12][12];
    unordered_set<string> ans_set;
    vector<string> ans;

    vector<string> findWords(vector<vector<char>>& _board, vector<string>& words) {
        board = _board;
        rows = board.size();
        cols = board[0].size();
        direction = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
        for (string word : words) {
            trie.insert(word);
        }

        for (int r = 0; r < rows; ++r) {
            for (int c = 0; c < cols; ++c) {
                int cur = board[r][c] - 'a';
                if (trie.son[cur]) {
                    visited[r][c] = true;
                    dfs(r, c, trie.son[cur]);
                    visited[r][c] = false;
                }
            }
        }
        for (string s : ans_set) ans.push_back(s);
        return ans;
    }
    void dfs(int row, int col, Trie* node) {
        if (node->str != "") {
            ans_set.insert(node->str);
        }
        for (pair<int, int> dir : direction) {
            int nr = row + dir.first;
            int nc = col + dir.second;
            if (0 <= nr && nr < rows && 0 <= nc && nc < cols) {
                if (!visited[nr][nc]) {
                    int nidx = board[nr][nc] - 'a';
                    if (node->son[nidx] != nullptr) {
                        visited[nr][nc] = true;
                        dfs(nr, nc, node->son[nidx]);
                        visited[nr][nc] = false;
                    }
                }
            }
        }
    }
};

下面官解,优化了visit数组用#代替,字典树另一写法

struct TrieNode {
    string word;
    unordered_map<char,TrieNode *> children;
    TrieNode() {
        this->word = "";
    }   
};

void insertTrie(TrieNode * root,const string & word) {
    TrieNode * node = root;
    for (auto c : word){
        if (!node->children.count(c)) {
            node->children[c] = new TrieNode();
        }
        node = node->children[c];
    }
    node->word = word;
}

class Solution {
public:
    int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    bool dfs(vector<vector<char>>& board, int x, int y, TrieNode * root, set<string> & res) {
        char ch = board[x][y];        
        if (!root->children.count(ch)) {
            return false;
        }
        root = root->children[ch];
        if (root->word.size() > 0) {
            res.insert(root->word);
        }

        board[x][y] = '#';
        for (int i = 0; i < 4; ++i) {
            int nx = x + dirs[i][0];
            int ny = y + dirs[i][1];
            if (nx >= 0 && nx < board.size() && ny >= 0 && ny < board[0].size()) {
                if (board[nx][ny] != '#') {
                    dfs(board, nx, ny, root,res);
                }
            }
        }
        board[x][y] = ch;

        return true;      
    }

    vector<string> findWords(vector<vector<char>> & board, vector<string> & words) {
        TrieNode * root = new TrieNode();
        set<string> res;
        vector<string> ans;

        for (auto & word: words){
            insertTrie(root,word);
        }
        for (int i = 0; i < board.size(); ++i) {
            for (int j = 0; j < board[0].size(); ++j) {
                dfs(board, i, j, root, res);
            }
        }        
        for (auto & word: res) {
            ans.emplace_back(word);
        }
        return ans;        
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值