212. Word Search II

Given a 2D board and a list of words from the dictionary, find all words in the board.spa

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.code

Example:blog

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

Output: 
["oath","pea","eat","rain"]["eat","oath"]

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

 

利用字典樹+深度優先遍歷的思想。對words中每一個word,創建一顆字典樹,每一個單詞的結尾字母上包含這個單詞的全部信息。以下圖:input

那麼在字母矩陣中找單詞,就能夠抽象爲,遍歷字母矩陣,尋找一條字典樹中的路徑,這個「路徑」的定義,若是某個節點包含單詞信息(上圖中黃色部分),則認爲找到一條路徑,即找到一個單詞。string

1.遍歷字母矩陣每一個字母,而且從字典樹的根節點開始搜索,若是字母是根節點的子樹,則繼續2。不然next字母。it

2.若是字母節點在tree樹中有單詞信息,則把該單詞加入返回的集合中。在矩陣中,訪問字母上下左右的四個字母,若是有本身的孩子,則繼續搜索下去。每次路徑搜索時,都把路徑中訪問過的節點,設置爲visited。io

3.遍歷結束,會把全部的單詞返回。class

 

 

 舉例:從‘o’開始遍歷字母矩陣,發現'o’ 在字典樹的根節點的孩子裏,尋找路徑的步驟移到‘o’節點(該過程是個遞歸),因而繼續遍歷其上(無),下(e),左(無),右(a),尋找有沒有哪一個鄰居是在‘o’的孩子裏。誒!發現e在本身的孩子節點裏;sed

而後繼續從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;
    }
};
相關文章
相關標籤/搜索