您的位置:首页 > 其它

LeetCode OJ 之 Word Search II (单词搜索 - 二)

2015-08-03 14:28 495 查看

题目:

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"]
.

Note:

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

click to show hint.

You would need to optimize your backtracking to pass the larger test. Could you stop backtracking earlier?
If the current candidate does not exist in all words' prefix, you could stop backtracking immediately. What kind of data structure could answer such query efficiently? Does a hash table work? Why or why not? How
about a Trie? If you would like to learn how to implement a basic trie, please work on this problem: Implement
Trie (Prefix Tree) first.

思路:

参考word search:http://blog.csdn.net/u012243115/article/details/42075915 。

如果直接采用word search的方法会超时,需要采用更加高效的查找方法。根据提示可以采用Trie树。

Trie树参考:http://blog.csdn.net/u012243115/article/details/47252213 。

即先构造一棵前缀树,然后对二维板的每个字符进行深搜。判断某个路径是否是某个单词。如果当前路径不是任何单词的前缀则立即返回。如果是,则继续递归。

代码:

class TrieNode
{
public:
// Initialize your data structure here.
bool isWord;
TrieNode *next[26];
TrieNode()
{
isWord = false;
for(int i = 0 ; i < 26 ; i++)
next[i] = NULL;
}
};

class Trie {
public:
Trie()
{
root = new TrieNode();
}

// Inserts a word into the trie.
void insert(string word)
{
int len = word.size();
TrieNode *p = root;
for(int i = 0 ; i < len ; i++)
{
//如果不存在,则建立新结点。如果存在,则继续向下
if(p->next[word[i] - 'a'] == NULL)
p->next[word[i] - 'a'] = new TrieNode();
p = p->next[word[i] - 'a'];
}
p->isWord = true;   //把最后一个结点的isWord置为true,表示从根结点到当前结点保存了一个单词
}

// Returns if the word is in the trie.
bool search(string word)
{
TrieNode *p = find(word);
return p != NULL && p->isWord;  //还要判断当前结点的isWord是否为真,为真才表示是个单词。如果为假,则表示word只是已存在单词的前缀
}

// Returns if there is any word in the trie
// that starts with the given prefix.
bool startsWith(string prefix)
{
TrieNode *p = find(prefix);
return p != NULL;   //和上面一个函数比较,这里由于查找前缀,因此不需要判断isWord
}

//查找key是否存在
TrieNode *find(string key)
{
int len = key.size();
TrieNode *p = root;
for(int i = 0 ; i < len && p != NULL ; i++)
{
p = p->next[key[i] - 'a'];
}
return p;
}
private:
TrieNode* root;     //注意:根结点并不表示字符
};

class Solution {
public:
void dfs(Trie &trie , vector<vector<char> > &board, string word, size_t i , size_t j, vector<vector<bool> > &visited , vector<string> &result)
{
if(i<0 || j<0 || i>=board.size() || j>= board[0].size())
return ;
//如果当前字母被访问过
if(visited[i][j])
return ;
word += board[i][j];

//这一步很重要,如果word不是某个单词的前缀,则提前返回(没有这一步结果超时了)
if(!trie.startsWith(word))
return ;
if(trie.search(word))
{
if(find(result.begin() , result.end() , word) == result.end())  //注意:可能board中重复找到已经找到的word,比如board={"aa"},word={"a"},因此需要判断result里是否已经找到。如果没找到,才加入到result
result.push_back(word);
}

//以上都不满足,说明当前字母符合条件,置为true,继续对当前单词的上下左右深搜
visited[i][j] = true;
if(i - 1 >= 0)
dfs(trie , board , word , i-1 , j , visited , result) ;
if(i + 1 < board.size())
dfs(trie , board , word , i+1 , j , visited , result) ;
if(j - 1 >= 0)
dfs(trie , board , word , i , j-1 , visited , result) ;
if(j + 1 < board[0].size())
dfs(trie , board , word , i , j+1 , visited , result) ;
//从board[i][j]点开始深搜完成后,visited要重置为false
visited[i][j] = false;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words)
{
Trie trie;
vector<string> result;
size_t len = words.size();

//先对所有单词构造一个trie树
for(int i = 0 ; i < len ; i++)
{
trie.insert(words[i]);
}
size_t row = board.size();
if(row == 0)
return result;
size_t col = board[0].size();
vector<vector<bool> > visited(row , vector<bool>(col , false)); //对已经访问过的字符标记

//然后对二维板上的每个字符进行深搜,使用trie树减少深搜时间
for(int i = 0 ; i < row ; i++)
{
for(int j = 0 ; j < col ; j++)
{
dfs(trie , board , "" , i , j , visited , result);
}
}
return result;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: