力扣:212. 单词搜索 II

题目:212. 单词搜索 II

难度: 困难

题目

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

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

示例1

在这里插入图片描述

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

示例2

在这里插入图片描述

输入:board = [[“a”,“b”],[“c”,“d”]], words = [“abcb”]
输出:[]

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 12
  • board[i][j] 是一个小写英文字母
  • 1 <= words.length <= 3 * 104
  • 1 <= words[i].length <= 10
  • words[i] 由小写英文字母组成
  • words 中的所有字符串互不相同

来源:力扣(LeetCode)
链接https://leetcode-cn.com/problems/word-search-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。



解题思路

这题的思路是前缀树+回溯,用前缀树存储某个单词的信息,四个方向回溯查找单词。
前缀树,也称单词数,单词只在某些结点上存储,同时每个结点都存储了其后缀。

class Solution {
public:
    struct TrieNode
    {
        string word;
        unordered_map<char, TrieNode*> next;
        TrieNode()
        {
            this->word = "";
        }
    };
    void trie_insert(TrieNode* root, string& word)
    {
        TrieNode* node = root;
        for (auto& ch : word)
        {
            if (!node->next.count(ch))
            {
                node->next[ch] = new TrieNode();
            }
            node = node->next[ch];
        }
        node->word = word;
    }
    int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    bool DFS(TrieNode* root, vector<vector<char>>& board, int x, int y, set<string>& res)
    {
        char ch = board[x][y];
        if (!root->next.count(ch))
        {
            return false;
        }
        root = root->next[ch];
        if (!root->word.empty())
        {
            res.insert(root->word);
        }
        //处理
        board[x][y] = '#';
        for (int i = 0; i < 4; i++)
        {
            int nx = x + dirs[i][0];
            int ny = y + dirs[i][1];
            if (nx >= 0 && nx < board.size() && ny >= 0 && ny < board[0].size())
            {
                if (board[nx][ny] != '#')
                {
                    DFS(root, board, nx, ny, res);
                }
            }
        }
        board[x][y] = ch;
        return true;
    }
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        TrieNode* root = new TrieNode();
        set<string> res;
        vector<string> ans;
        //构建前缀树
        for (auto& word : words)
        {
            trie_insert(root, word);
        }
        //DFS
        for (int i = 0; i < board.size(); i++)
        {
            for (int j = 0; j < board[0].size(); j++)
            {
                DFS(root, board, i, j, res);
            }
        }
        //处理输出
        for (auto& word : res)
        {
            ans.push_back(word);
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗夜无风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值