Leetcode 212. 单词搜索 II 字典树+DFS

给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

示例:

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

输出: 
["eat","oath"]

说明:
你可以假设所有输入都由小写字母 a-z 组成。

提示:

  • 你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
  • 如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)

https://mp.csdn.net/postedit/88070633这篇博客里有建立字典树的写法,这里就不介绍了。

这个题我们把words建立字典树,然后dfs二维网格board,判断有没有构成的单词。

class Solution
{
public:
    struct node
    {
        node *nxt[26];
        string str;
        node() : str("") 
        {
            for(int i=0;i<26;i++)
            {
                nxt[i]=NULL;
            }
        }
    };
    struct Trie 
    {
        node *root;
        Trie() : root(new node()) {}
        void insert(string s)
        {
            node *temp = root;
            for (int i=0;i<s.size();i++) 
            {
                if ((temp->nxt)[s[i]-'a']==NULL) 
                {
                    (temp->nxt)[s[i]-'a'] = new node();
                }
                temp= (temp->nxt)[s[i]-'a'];
            }
            temp->str = s;
        }
    };
    vector<string> findWords(vector<vector<char> >& board, vector<string>& words) 
    {
        vector<string> res;
        if (words.empty() || board.empty() || board[0].empty()) 
            return res;
        vector<vector<bool> > visit(board.size(), vector<bool>(board[0].size(), false));  //定义一个二维的vistor 大小等于borad 初始化为false;
        Trie T;
        for (auto &a : words) T.insert(a);  //插入字符串,构建字典树
        for (int i = 0; i < board.size(); ++i) 
        {
            for (int j = 0; j < board[i].size(); ++j)
            {
                if (T.root->nxt[board[i][j] - 'a']) 
                {
                    search(board, T.root->nxt[board[i][j] - 'a'], i, j, visit, res);
                }
            }
        }
        return res;
    }
    void search(vector<vector<char> > &board, node *p, int i, int j, vector<vector<bool> > &visit, vector<string> &res) 
    { 
        if (!p->str.empty())
        {
            res.push_back(p->str);
            p->str.clear();
        }
        int d[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        visit[i][j] = true;
        for (int x=0;x<4;x++) 
        {
            int nx = d[x][0] + i;
            int ny = d[x][1] + j;
            if (nx >= 0 && nx < board.size() && ny >= 0 && ny < board[0].size() && !visit[nx][ny] && p->nxt[board[nx][ny] - 'a'])
            {
                search(board, p->nxt[board[nx][ny] - 'a'], nx, ny, visit, res);
            }
        }
        visit[i][j] = false;
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值