Leetcode #212 Word Search II

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.

For example,
Given words = ["oath","pea","eat","rain"] and board =

[
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]
Return ["eat","oath"].

开始直接重用 第79道Word Serach的代码 tle了,代码如下:

class Solution{
public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        vector<string> ret;
        for(auto word : words)
            if (exist(board, word))
                ret.push_back(word);
        return ret;
    }

    bool exist(vector<vector<char>>& board, string word) {
        if (board.empty() && word.empty()) return true;
        else if (board.empty()) return false;
        int row = board.size(), col = board[0].size();
        for(int i = 0; i < row; i++)
            for(int j = 0; j < col; j++)
                if ( dfs(board, i, j, word, 0) ) return true;
        return false;
    }

    bool dfs(vector<vector<char>>& board, int i, int j, string word, int word_start){

        if(i < 0 || i >= board.size() || j < 0 || j >= board[0].size()) return false;
        if(board[i][j] == '*' || word[word_start] != board[i][j])  return false;
        if (word_start == word.size() - 1)  return true;

        char temp = board[i][j]; board[i][j] = '*';
        if(dfs(board, i - 1, j, word, word_start + 1) || dfs(board, i + 1, j, word, word_start + 1)
                || dfs(board, i, j - 1, word, word_start + 1) || dfs(board, i, j + 1, word, word_start + 1)) {
            board[i][j] = temp;
            return true;
        }
        board[i][j] = temp;
        return false;
    }
};

        本题的hint中提到了trie(而它的前一个题211 Add and Search Word - Data structure design是个典型的trie),用trie的思路是先把所给的单词加到Trie字典里,然后再通过回溯(深搜)遍历矩阵中所有可能的单词,将存在于字典中的单词全部找出。另外,代码中需要注意的是,在回溯的过程中不同的路径上有可能会出现重复的单词,所以要用set记录这些单词,保证一个单词只被存储一次。等回溯结束,再将这些单词存到vector中。
         AC的代码如下,耗时是88ms。

typedef struct TrieNode{
    TrieNode* child[26];
    bool isendWord;

    TrieNode():isendWord(false){
        for (int i = 0; i < 26; i ++)
            child[i] = NULL;
    }
}* trie_node;

class Trie {
public:
    Trie(vector<string>& words){
        root = new TrieNode();
        for(auto word : words) addWord(word);
    }

    trie_node getRoot(){
        return root;
    }

    void addWord(const string& word){
        trie_node p = root;
        for (int i = 0; i < word.size(); i ++) {
            int j = word[i] - 'a';
            if(!p -> child[j])
                p -> child[j] = new TrieNode();
            p = p -> child[j];
        }
        p -> isendWord = true;
    }

private:
    trie_node root;
};

class Solution {
public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {

        trie_node root = (new Trie(words)) -> getRoot();

        set<string> res_set;
        for (int i = 0; i < board.size(); i++)
            for(int j = 0; j < board[0].size(); j++)
                searchWord(board, i, j, root, "", res_set);
        vector<string> res;
        for(auto word : res_set) res.push_back(word);
        return res;
    }

    void searchWord (vector< vector<char> >& board, int i, int j, trie_node root, string word, set<string>& res_set) {

        if(i < 0 || j < 0 || i >= board.size() || j >= board[0].size() || board[i][j] == '*') return;

        if(root -> child[board[i][j] - 'a']){
            word += board[i][j];
            root = root -> child[board[i][j] - 'a'];
            if(root -> isendWord) res_set.insert(word);

            char temp = board[i][j];
            board[i][j] = '*';
            searchWord(board, i - 1, j, root, word, res_set);
            searchWord(board, i + 1, j, root, word, res_set);
            searchWord(board, i, j - 1, root, word, res_set);
            searchWord(board, i, j + 1, root, word, res_set);
            board[i][j] = temp;

        }
    }

};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值