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.

Example:

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

Output: ["eat","oath"]

Note:
You may assume that all inputs are consist of lowercase letters a-z.

 

利用字典树+深度优先遍历的思想。对words中每个word,建立一颗字典树,每个单词的结尾字母上包含这个单词的所有信息。如下图:

那么在字母矩阵中找单词,就可以抽象为,遍历字母矩阵,寻找一条字典树中的路径,这个“路径”的定义,如果某个节点包含单词信息(上图中黄色部分),则认为找到一条路径,即找到一个单词。

1.遍历字母矩阵每个字母,并且从字典树的根节点开始搜索,如果字母是根节点的子树,则继续2。否则next字母。

2.如果字母节点在tree树中有单词信息,则把该单词加入返回的集合中。在矩阵中,访问字母上下左右的四个字母,如果有自己的孩子,则继续搜索下去。每次路径搜索时,都把路径中访问过的节点,设置为visited。

3.遍历结束,会把所有的单词返回。

 

 

 举例:从‘o’开始遍历字母矩阵,发现'o’ 在字典树的根节点的孩子里,寻找路径的步骤移到‘o’节点(该过程是个递归),于是继续遍历其上(无),下(e),左(无),右(a),寻找有没有哪个邻居是在‘o’的孩子里。诶!发现e在自己的孩子节点里;

然后继续从e开始寻找,上(e,但已访问过,pass),下(i),左(无),右(t)。诶!发现t在自己的孩子节点。。。直到h,发现h的节点信息里有单词,诶!加入到res里。这条路径访问就结束了。然后继续从a开始访问,寻找下一条路径。把字符矩阵访问结束后,可得到所有的单词。

 

附代码:

 

#include <map>

struct pos {
    int x;
    int y; 
    pos(int x,int y):x(x),y(y) {};
    pos():x(0),y(0) {};
};

struct treeNode
{
    string str;
    treeNode* child[26];

    treeNode()
    {
        str = "";
        for(int i = 0;i<26;i++)
            child[i] = NULL;
    }
};

struct WordTree
{
    treeNode* root;

    WordTree()
    {
        root = new treeNode();
    }    

    //这样构建字典树
    //保证相同的单词,只出现一次
    void insert(string s)
    {
        int len = s.length();
        if(len<=0) return;
        treeNode* p=root;
        for(int i=0;i<len;i++)
        {   
            char tmp = s[i];
            int index = tmp - 'a';
            if(!p->child[index]) {
                p->child[index] = new treeNode();
            }
            p = p->child[index];
        }
        p->str = s;
    }
};


void search(vector<vector<char> >& board,treeNode* p, int i,int j,vector<string>& res,vector<vector<bool>>& visited)
{
    if(!p->str.empty())
    {
        res.push_back(p->str);
        p->str.clear();
    }
    visited[i][j] = true;
    int direction[][2] = {{-1,0},{1,0},{0,-1},{0,1}};
    for (int k = 0; k < 4; k++)
    {
        int nx = i + direction[k][0];
        int ny = j + direction[k][1];

        //先判断坐标的有效性
        if(nx>=0 && nx<board.size())
        {
            if(ny>=0 && ny<board[0].size())
            {
                //存在字典树中,且本次路径中未被访问到
                if(p->child[board[nx][ny]-'a']&&!visited[nx][ny])
                {
                    search(board,p->child[board[nx][ny]-'a'],nx,ny,res,visited);
                }
            }
        }    
    }
    visited[i][j] = false;
}

class Solution {
public:
    vector<string> findWords(vector<vector<char> >& board, vector<string>& words) {
        vector<string> res;
        if (words.empty() || board.empty() || board[0].empty()){
            return res;
        }                
        WordTree tree;
        vector<vector<bool> > visited(board.size(), vector<bool>(board[0].size(), false));

        //构建字典树
        for (int i=0; i<words.size(); i++)
        {
            tree.insert(words[i]);
        }
        for (int i = 0; i < board.size(); ++i) {
            for (int j = 0; j < board[i].size(); ++j) {
                if (tree.root->child[board[i][j] - 'a']) {
                    search(board, tree.root->child[board[i][j] - 'a'], i, j, res,visited);
                }
            }
        }
        return res;
    }
};

 

 

 

 

转载于:https://www.cnblogs.com/LUO77/p/10553971.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值