leetcode#212 单词搜索II

本文介绍了LeetCode 212题目的解决方案,即在二维字符网格中查找字典中的单词。算法通过构建Trie树来优化搜索,并使用深度优先搜索(DFS)进行回溯。在每个单元格开始,如果字典中存在以该单元格字母开头的单词,就进行递归搜索,检查路径是否与字典中的单词匹配。最后,返回所有找到的单词。
摘要由CSDN通过智能技术生成

leetcode#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"]

思路:

该算法的整个工作流程是直观的,包括在二维网格中的每个单元上循环和从单元开始的递归函数调用。这是算法的框架。

  • 我们根据字典中的单词构建一个 Trie,稍后将用于匹配过程。
  • 从每个单元格开始,如果字典中存在以单元格中的字母开头的单词,则我们开始回溯探索(即 backtracking(cell))。
  • 在递归函数 backtracking(cell) 调用过程中,我们探索当前单元格周围的相邻单元格(即 neighborCell)以进行下一个递归调用 backtracking(neighborCell)。在每次调用时,我们都会检查到目前为止遍历的字母序列是否与字典中的任何单词匹配,这需要借助于我们在开始时构建的 Trie 数据结构。

代码

#include <bits/stdc++.h>
using namespace std;
struct node
{
    bool is_word;
    node *next[26];
    node() : is_word(false), next() {}
};
class Solution
{
private:
    node *root = new node();
    vector<string> ans;
    unordered_map<string, int> mp;
    int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
    int m, n;

public:
    void init(vector<string> &words)
    {
        int num = words.size();
        for (int i = 0; i < num; ++i)
        {
            node *now = root;
            for (int j = 0; j < words[i].length(); ++j)
            {
                if (!now->next[words[i][j] - 'a'])
                    now->next[words[i][j] - 'a'] = new node();
                now = now->next[words[i][j] - 'a'];
            }
            now->is_word = true;
        }
    }
    void dfs(int x, int y, node *now, vector<vector<char>> &board, string res)
    {
        if (now->is_word && mp.find(res) == mp.end())
            mp[res]++, ans.push_back(res);
        for (int i = 0; i < 4; ++i)
        {
            int xx = x + dir[i][0];
            int yy = y + dir[i][1];
            if (xx >= 0 && xx < m && yy >= 0 && yy < n && board[xx][yy] != '.' && now->next[board[xx][yy] - 'a'])
            {
                char ch = board[xx][yy];
                board[xx][yy] = '.';
                res += ch;
                dfs(xx, yy, now->next[ch - 'a'], board, res);
                res.pop_back();
                board[xx][yy] = ch;
            }
        }
    }
    vector<string> findWords(vector<vector<char>> &board, vector<string> &words)
    {
        m = board.size(), n = board[0].size();
        init(words);
        for (int i = 0; i < m; ++i)
            for (int j = 0; j < n; ++j)
                if (root->next[board[i][j] - 'a'] != NULL)
                {
                    char ch = board[i][j];
                    string tmp = "";
                    tmp += board[i][j];
                    board[i][j] = '.';
                    dfs(i, j, root->next[ch - 'a'], board, tmp);
                    board[i][j] = ch;
                }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值