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

思路:

好奇怪啊,我自己写了一个DFS的代码,这种TLE。网上看看发现要用字典树,其实就是把查询给定字符串的过程简化了。

可是我的代码也查询的很容易啊。为什么我的代码TLE,字典树代码就只要56ms呢?

字典数Trie代码:其中标记使用过字符的方式值得学习

class Solution2 {
class Trie{
public:
Trie *children[]; //指向其子序列 从'a'到'z'
bool leaf; //该结点是否是叶子结点
int idx; //如果该节点是叶子结点, idx是该单词在vector中的序号
Trie()
{
this->leaf = false;
this->idx = ;
fill_n(this->children, , nullptr);
}
}; public:
void insertWords(Trie *root, vector<string>& words, int idx)
{
int pos = , len = words[idx].size();
while(pos < len)
{
if(NULL == root->children[words[idx][pos] - 'a'])
root->children[words[idx][pos] - 'a'] = new Trie();
root = root->children[words[idx][pos++] - 'a'];
}
root->leaf = true;
root->idx = idx;
} Trie * buildTrie(vector<string>& words)
{
Trie * root = new Trie();
for(int i = ; i < words.size(); ++i)
insertWords(root, words, i);
return root;
} void checkWords(vector<vector<char>>& board, int i, int j, int row, int col, Trie *root, vector<string> &res, vector<string>& words)
{
if(i < || j < || i >= row || j >= col) return;
if(board[i][j] == 'X') return; //已经访问过
if(NULL == root->children[board[i][j] - 'a']) return;
char temp = board[i][j];
if(root->children[temp - 'a']->leaf) //这是叶子结点
{
res.push_back(words[root->children [temp - 'a']->idx]);
root->children[temp - 'a']->leaf = false; //标为false表示已经找到之歌单词了
}
board[i][j] = 'X'; //标记这个字母为已找过 checkWords(board, i-, j, row, col, root->children[temp-'a'], res, words);
checkWords(board, i+, j, row, col, root->children[temp-'a'], res, words);
checkWords(board, i, j-, row, col, root->children[temp-'a'], res, words);
checkWords(board, i, j+, row, col, root->children[temp-'a'], res, words); board[i][j] = temp;
} vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
vector<string> res;
int row = board.size();
if(==row) return res;
int col = board[].size();
if(==col) return res;
int wordCount = words.size();
if(==wordCount) return res; Trie *root = buildTrie(words); int i,j;
for(i = ; i<row; i++)
{
for(j=; j<col && wordCount > res.size(); j++)
{
checkWords(board, i, j, row, col, root, res, words);
}
}
return res;
} };

我自己的代码:

class Solution {
public:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
if(board.empty()) return vector<string>(); vector<string> ans;
//对所有入口遍历
for(int i = ; i < board.size(); ++i)
{
for(int j = ; j < board[].size(); ++j)
{
string scur;
unordered_set<int> myset;
getAnswer(i, j, board, words, scur, ans, myset);
}
}
return ans;
} void getAnswer(int i, int j, vector<vector<char>>& MyBoard, vector<string> ResWords, string scur, vector<string>& ans, unordered_set<int> myset)
{
if(ResWords.empty()) return; //没有更多的单词
if(i < || j < || i >= MyBoard.size() || j >= MyBoard[].size()) return;
if(myset.find(i * MyBoard[].size() + j) != myset.end()) return; //该字母已经使用过
myset.insert(i * MyBoard[].size() + j);
vector<string> newResWords;
//对所有剩下待匹配的单词(即前面字母都符合,并且没有完全匹配的单词)
for(int k = ; k < ResWords.size(); ++k)
{
if(MyBoard[i][j] == ResWords[k][scur.length()] && ResWords[k].length() == scur.length() + ) //新字母与单词匹配 且单词没有更多的字母 压入答案
ans.push_back(scur + MyBoard[i][j]);
else if(MyBoard[i][j] == ResWords[k][scur.length()]) //若字母匹配 压入新的剩余单词
newResWords.push_back(ResWords[k]);
}
scur += MyBoard[i][j]; getAnswer(i + , j, MyBoard, newResWords, scur, ans, myset);
getAnswer(i - , j, MyBoard, newResWords, scur, ans, myset);
getAnswer(i, j + , MyBoard, newResWords, scur, ans, myset);
getAnswer(i, j - , MyBoard, newResWords, scur, ans, myset);
}
};

【leetcode】Word Search II(hard)★的更多相关文章

  1. 【leetcode】Word Ladder II

      Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation ...

  2. 【leetcode】Word Break II

    Word Break II Given a string s and a dictionary of words dict, add spaces in s to construct a senten ...

  3. 【leetcode】Word Search

    Word Search Given a 2D board and a word, find if the word exists in the grid. The word can be constr ...

  4. 【leetcode】Word Search (middle)

    今天开始,回溯法强化阶段. Given a 2D board and a word, find if the word exists in the grid. The word can be cons ...

  5. 【leetcode】Word Break II (hard)★

    Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...

  6. 【leetcode】Word Ladder II(hard)★ 图 回头看

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

  7. Java for 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 mus ...

  8. [LeetCode] 212. Word Search II 词语搜索 II

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

  9. 【LeetCode】47. Permutations II 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:递归 方法二:回溯法 日期 题目地址:htt ...

随机推荐

  1. 【PHP面向对象(OOP)编程入门教程】10.__set(),__get(),__isset(),__unset()四个方法的应用

    一般来说,总是把类的属性定义为private,这更符合现实的逻辑.但是, 对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数”__get()”和”__set()”来获取和赋值其属性 ...

  2. WordPress文章浏览历史插件

    选自:http://www.ludou.org/wordpress-recently-viewed.html 最近有很多网友问我,露兜博客右边栏底部的 您刚刚看过 栏目是怎么实现.其实我也是参考的这篇 ...

  3. MongoDB的学习和使用(查询find)

    语法 MongoDB 查询数据的语法格式如下: >db.COLLECTION_NAME.find() find() 方法以非结构化的方式来显示所有文档. 如果你需要以易读的方式来读取数据,可以使 ...

  4. UOJ#35 —— 后缀排序

    1.题目大意:后缀数组模板题 2.分析:汝佳的书上的代码的有bug,还有那个n是字符串长度+1,''也要加入排序的 存个模板QAQ #include <cstdio> #include & ...

  5. C++基础知识(1)----文件操作

    参照 小菜鸟上校 的博客 // file operat.cpp : 定义控制台应用程序的入口点. /*上述例子的主要功能是将一个文件的内容复制到另一个文件中, 这个功能主要由一个函数copy来实现.它 ...

  6. BZOJ 2654: tree

    Description \(n\) 个点, \(m\) 条边,边有权值和黑/白色,求含有 \(need\) 个白边的生成树. Sol 二分+Kruskal. 将每条白边都加上一个权值,然后跑最小生成树 ...

  7. 读书笔记-Android初学笔记

    Eclipse [ADT] 源 https://dl-ssl.google.com/android/eclipse Notice that no matter what scenario causes ...

  8. swing复制文本框内容

    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); //得到系统剪贴板 String text = jTex ...

  9. JSP Servlet WEB生命周期

    [转载] JavaWeb的生命周期是由Servlet容器来控制的总的来说分为三个阶段1.启动阶段:加载web应用相关数据,创建ServletContext对象,对Filter和servlet进行初始化 ...

  10. NUI四种提交数据方式c

    方式一: 1)前端页面 2)逻辑流参数设置 方式二: 1)前端页面 2)逻辑流参数设置 方式三:  1)前端页面 2)逻辑流参数设置 方式四: 1)前端页面 2)逻辑流参数设置