面试150——第六周

目录

被围绕的区域

克隆图

除法求值

课程表

课程表②

最小基因变化

蛇梯棋

单词接龙

前缀树

添加和搜索单词

任务调度器

单词搜索二

电话号码的自由组合

组合

全排列

全排列二

组合总和

N皇后二

括号生成

单词搜索


被围绕的区域

解法:递归

从四个边,以当前位置为'O'为起始位置进行递归标记

后面再次遍历时,如果该区域为'O'且被没有标记,说明该地方是被围绕的区域,修改'O' 为 'X',往后进行枚举...

cpp 复制代码
class Solution
{
public:
    bool vis[201][201] = {false};
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    int n, m;
    void dfs(vector<vector<char>> &board, int i, int j)
    {
        vis[i][j] = true;
        for (int k = 0; k < 4; k++)
        {
            int x = dx[k] + i, y = dy[k] + j;
            if (x >= 0 && x < n && y >= 0 && y < m && !vis[x][y] && board[x][y] == 'O')
            {
                dfs(board, x, y);
            }
        }
    }
    void solve(vector<vector<char>> &board)
    {
        n = board.size(), m = board[0].size();
        for (int i = 0; i < n; i++)
        {
            if (board[i][0] == 'O' && !vis[i][0])
            {
                dfs(board, i, 0);
            }
            if (board[i][m - 1] == 'O' && !vis[i][m - 1])
            {
                dfs(board, i, m - 1);
            }
        }
        for (int j = 0; j < m; j++)
        {
            if (board[0][j] == 'O' && !vis[0][j])
            {
                dfs(board, 0, j);
            }
            if (board[n - 1][j] == 'O' && !vis[n - 1][j])
            {
                dfs(board, n - 1, j);
            }
        }
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                // 是 O 且没有被递归到说明就是被环绕的区域
                if (board[i][j] == 'O' && !vis[i][j])
                {
                    board[i][j] = 'X';
                }
            }
        }
    }
};

克隆图

前提:使用 hash 来储存原节点与克隆节点的映射

思路1:dfs

当前节点为 nullptr,返回 nullptr

当前节点在 hash 中找到了,说明当前递归的节点被克隆了,通过原节点返回克隆节点

此时当前节点 node 一定没有被克隆,克隆节点 clone 进行 new,之后加入到 hash 中

遍历当前节点的邻居节点进行递归,把递归结果保存到 clone 的 neighbors 中

cpp 复制代码
class Solution
{
public:
    // 原节点 -> 克隆节点
    unordered_map<Node *, Node *> hash;
    Node *cloneGraph(Node *node)
    {
        if (node == nullptr)
            return nullptr;
        // 递归时克隆过了直接返回
        if (hash.contains(node))
        {
            return hash[node];
        }
        Node *cloneNode = new Node(node->val);
        hash[node] = cloneNode;
        // 遍历原节点的邻居
        for (auto &neighbor : node->neighbors)
        {
            // 收集克隆节点的邻居
            cloneNode->neighbors.push_back(cloneGraph(neighbor));
        }
        return cloneNode;
    }
};

思路2:bfs

创建队列保存被克隆的原节点

每次获取队头节点 tmp,遍历该节点的所有邻居节点:

如果当前邻居节点没有被克隆,就要进行克隆 clone,之后保存到 hash 中

此时通过原节点一定能找到克隆节点 hash[tmp],把邻居节点的克隆节点 clone保存在 hash[tmp] 中

cpp 复制代码
class Solution
{
public:
    // 原节点 -> 克隆节点
    unordered_map<Node *, Node *> hash;
    Node *cloneGraph(Node *node)
    {
        if (node == nullptr)
        {
            return nullptr;
        }
        queue<Node *> q;
        // 初始化条件
        q.push(node);
        Node *clone = new Node(node->val);
        hash[node] = clone;
        while (!q.empty())
        {
            Node *tmp = q.front();
            q.pop();
            for (auto &neighbor : tmp->neighbors)
            {
                // 哈希表找不到映射说明当前节点neighbor还没有被克隆
                if (!hash.contains(neighbor))
                {
                    Node *clone = new Node(neighbor->val);
                    hash[neighbor] = clone;
                    // 把克隆后的原节点放入到队列中
                    q.push(neighbor);
                }
                // 到这里,当前节点neighbor一定被克隆了
                // 把它加入到克隆节点tmp的邻居中(隐藏条件:队列中的节点一定被克隆过的)
                hash[tmp]->neighbors.push_back(hash[neighbor]);
            }
        }
        return clone;
    }
};

除法求值

解法:dfs

建图,比如 a,b = 3,就要建 a->b 3 和 b->a 1/3,使用hash<string,vector<pair<string,double>> 进行储存

图遍历,比如求 a,c 那我就从 a 开始一直递归,直到找到c,也就是 a->b->c,此时累乘的结果是答案(注意处理边界,因为还要 a->b->a 的情况,要使用vis对当前遍历节点进行标记)

cpp 复制代码
class Solution
{
public:
    unordered_map<string, vector<pair<string, double>>> hash;
    unordered_set<string> vis;
    double tmp1;
    double dfs(const string &begin, const string &end, double tmp)
    {
        if (begin == end)
        {
            return tmp;
        }
        if (vis.contains(begin))
        {
            return -1;
        }
        vis.insert(begin);
        for (auto &[beginNext, val] : hash[begin])
        {
            double ans = dfs(beginNext, end, tmp * val);
            if (ans != -1)
            {
                return ans;
            }
        }
        return -1;
    }
    vector<double> calcEquation(vector<vector<string>> &equations, vector<double> &values, vector<vector<string>> &queries)
    {
        // 建图
        for (int i = 0; i < equations.size(); i++)
        {
            hash[equations[i][0]].push_back({equations[i][1], values[i]});
            hash[equations[i][1]].push_back({equations[i][0], 1 / values[i]});
        }
        vector<double> ret;
        for (int i = 0; i < queries.size(); i++)
        {
            string begin = queries[i][0];
            string end = queries[i][1];
            if (!hash.contains(begin))
            {
                ret.push_back(-1);
            }
            else
            {
                vis.clear();
                ret.push_back(dfs(begin, end, 1));
            }
        }
        return ret;
    }
};

课程表

解法:拓扑排序

建图,存入度

使用拓扑排序(入度为0的入队列,bfs遍历)判断是否有课程入度不为0,有就完成返回false

cpp 复制代码
class Solution
{
public:
    bool canFinish(int numCourses, vector<vector<int>> &prerequisites)
    {
        unordered_map<int, vector<int>> hash;
        vector<int> in(numCourses);
        for (int i = 0; i < prerequisites.size(); i++)
        {
            // b->a
            int a = prerequisites[i][0];
            int b = prerequisites[i][1];
            hash[b].push_back(a);
            in[a]++;
        }
        queue<int> q;
        for (int i = 0; i < numCourses; i++)
        {
            if (in[i] == 0)
            {
                q.push(i);
            }
        }
        if (q.size() == 0)
        {
            return false;
        }
        int cnt = 0;
        while (!q.empty())
        {
            cnt++;
            int tmp = q.front();
            q.pop();
            for (auto &numCourse : hash[tmp])
            {
                if ((--in[numCourse]) == 0)
                {
                    q.push(numCourse);
                }
            }
        }
        // 或者是再遍历一遍来看看是否in中还有不等于0的课桌存在
        return cnt == numCourses;
    }
};

课程表②

解法:拓扑排序

按照拓扑排序的顺序依次当前课程即可,如果不能完成就返回{}

cpp 复制代码
class Solution
{
public:
    vector<int> findOrder(int numCourses, vector<vector<int>> &prerequisites)
    {
        vector<vector<int>> hash(numCourses);
        vector<int> in(numCourses);
        for (int i = 0; i < prerequisites.size(); i++)
        {
            // b->a
            int a = prerequisites[i][0];
            int b = prerequisites[i][1];
            hash[b].push_back(a);
            in[a]++;
        }
        queue<int> q;
        vector<int> ret;
        for (int i = 0; i < numCourses; i++)
        {
            if (in[i] == 0)
            {
                q.push(i);
                ret.push_back(i);
            }
        }
        if (q.size() == 0)
        {
            return ret;
        }
        int cnt = 0;
        while (!q.empty())
        {
            cnt++;
            int tmp = q.front();
            q.pop();
            for (auto &numCourse : hash[tmp])
            {
                if ((--in[numCourse]) == 0)
                {
                    ret.push_back(numCourse);
                    q.push(numCourse);
                }
            }
        }
        if (cnt != numCourses)
        {
            return {};
        }
        return ret;
    }
};

最小基因变化

cpp 复制代码
class Solution
{
public:
    unordered_map<string, bool> hash;
    queue<string> q;
    char gene[4] = {'A', 'G', 'C', 'T'};
    bool IsEnd(const string &s, const string &end)
    {
        // 遍历出所有的情况
        for (int i = 0; i < s.size(); i++)
        {
            for (int j = 0; j < 4; j++)
            {
                string tmp = s;
                tmp[i] = gene[j];
                // 找到终点直接返回变化次数
                if (tmp == end)
                {
                    return true;
                }
                if (hash.contains(tmp) && hash[tmp] == false)
                {
                    q.push(tmp);
                    hash[tmp] = true;
                }
            }
        }
        return false;
    }
    int minMutation(string startGene, string endGene, vector<string> &bank)
    {
        bool vis = false;
        for (auto &b : bank)
        {
            if (b == endGene)
            {
                vis = true;
            }
            hash[b] = false;
        }
        if (!vis)
        {
            return -1;
        }
        q.push(startGene);
        int ret = 0;
        while (!q.empty())
        {
            ret++;
            int sz = q.size();
            while (sz--)
            {
                string tmp = q.front();
                q.pop();
                if (IsEnd(tmp, endGene))
                {
                    return ret;
                }
            }
        }
        return -1;
    }
};

蛇梯棋

解法:bfs

与上题思路类似:都是通过队列的方式进行bfs,同时使用数组进行标记走过的位置

但是关键是要解决:如何把值转化成对应坐标?

队列放值还是坐标?

放值好:值转成坐标后,如果坐标不为-1,需要进行跳转,这里就直接值入队列完成跳转操作

cpp 复制代码
class Solution
{
public:
    int snakesAndLadders(vector<vector<int>> &board)
    {
        int n = board.size();
        bool vis[410] = {false};
        queue<int> q;
        int ret = 0;
        // 起点也要进行标记
        vis[1] = true;
        q.push(1);
        while (!q.empty())
        {
            ret++;
            int sz = q.size();
            while (sz--)
            {
                int tmp = q.front();
                q.pop();

                for (int i = tmp + 1; i <= min(tmp + 6, n * n); i++)
                {
                    // 值转换成坐标
                    int x1 = (i - 1) / n, y1 = (i - 1) % n;
                    int x = n - 1 - x1, y = y1;
                    if (x1 % 2 != 0)
                    {
                        y = n - 1 - y1;
                    }
                    // 标记下一个位置
                    int next = i;
                    if (board[x][y] > 0)
                    {
                        next = board[x][y];
                    }
                    if (!vis[next])
                    {
                        vis[next] = true;
                        // 走到了终点直接返回
                        if (next == n * n)
                        {
                            return ret;
                        }
                        q.push(next);
                    }
                }
            }
        }
        return -1;
    }
};

单词接龙

最小基因变化的别的场景

前缀树

解法:根据前缀树

单纯靠前缀树(多叉数)的构建:数组开辟26个位置或者哈希表的方式储存节点,使用bool对当前是否是结尾字符的标记

cpp 复制代码
class Trie
{
public:
    struct Node
    {
        Node *son[26] = {nullptr};

        bool end = false;
    };
    Node *root = new Node;
    Trie()
    {
    }

    void insert(string word)
    {
        Node *cur = root;
        int n = word.size();
        for (int i = 0; i < n; i++)
        {
            Node *tmp = cur->son[word[i] - 'a'];
            if (tmp == nullptr)
            {
                tmp = new Node;
                // 赋值
                cur->son[word[i] - 'a'] = tmp;
            }
            // 标记放循环外面
            if (i == n - 1)
            {
                tmp->end = true;
            }
            cur = tmp;
        }
    }
    int find(const string &tmp)
    {
        Node *cur = root;
        for (auto &ch : tmp)
        {
            Node *t = cur->son[ch - 'a'];
            if (t == nullptr)
            {
                return 0;
            }
            cur = t;
        }
        // 完整
        if (cur->end == true)
        {
            return 1;
        }
        // 前缀
        return 2;
    }
    bool search(string word)
    {
        int ret = find(word);
        if (ret == 0 || ret == 2)
        {
            return false;
        }
        return true;
    }

    bool startsWith(string prefix)
    {
        int ret = find(prefix);
        if (ret == 0)
        {
            return false;
        }
        // 返回1和返回2都是前缀
        return true;
    }
};

添加和搜索单词

解法:前缀树

在前缀树的基础上多了一步.的处理:

遍历26个节点,看看当前节点不为空且能让剩下的单词在前缀树上,那么他就可以构建成功

cpp 复制代码
class WordDictionary
{
public:
    struct Node
    {
        Node *son[26] = {nullptr};
        bool end = false;
    };
    Node *root = new Node;
    int n = 0;
    WordDictionary()
    {
    }

    void addWord(string word)
    {
        Node *cur = root;
        for (auto &ch : word)
        {
            Node *tmp = cur->son[ch - 'a'];
            if (tmp == nullptr)
            {
                tmp = new Node;
                cur->son[ch - 'a'] = tmp;
            }
            cur = tmp;
        }
        cur->end = true;
    }
    bool dfs(Node *r, const string &word, int i)
    {
        if (i == n)
        {
            return r->end;
        }
        if (word[i] == '.')
        {
            for (int j = 0; j < 26; j++)
            {
                if (r->son[j] != nullptr && dfs(r->son[j], word, i + 1))
                {
                    return true;
                }
            }
        }
        else
        {
            Node *tmp = r->son[word[i] - 'a']; // 这里i为4?
            if (tmp != nullptr && dfs(tmp, word, i + 1))
            {
                return true;
            }
        }
        return false;
    }
    bool search(string word)
    {
        Node *cur = root;
        n = word.size();
        if (dfs(root, word, 0))
        {
            return true;
        }
        return false;
    }
};

任务调度器

解法:构造

此时最短间隔: (n + 1) * (m - 1) + 1 = 4 * 3 + 1 = 13,第一行到第三个行剩下的位置就可以安排任务进行填充;如果个数超过 9 个就填充在每一行的最后一个

总任务个数 - 最短间隔 + 最短间隔,其实答案也就是总任务个数;而上面的 (n + 1) * (m - 1) + 1 中的 + 1并不一定每次都使用,这个要根据最多任务的个数进行计算(我理解的就是最后一行的个数),所有最终答案是 (总任务个数,(n + 1) * (m - 1) + lastLineCnt)取最大值

cpp 复制代码
class Solution
{
public:
    int leastInterval(vector<char> &tasks, int n)
    {
        int arr[26] = {0};
        int maxTask = INT_MIN;
        for (auto task : tasks)
        {
            int pos = task - 'A';
            arr[pos]++;
            if (maxTask < arr[pos])
            {
                maxTask = arr[pos];
            }
        }
        int LastTaskCnt = 0;
        for (auto &ch : arr)
        {
            if (ch == maxTask)
            {
                LastTaskCnt++;
            }
        }
        // n + 1 每行需要安排多少个任务
        // maxTask - 1 最多要安排多少行任务
        // 最后一行安排的任务个数 LastTaskCnt
        return max((int)tasks.size(), (n + 1) * (maxTask - 1) + LastTaskCnt);
    }
};

单词搜索二

解法:dfs + 前缀树

单纯使用 dfs 进行暴搜的话会超时,要先进行预处理,也就是通过单词列表中的每个单词构建前缀树,再dfs过程就可以直接判断当前节点的指定子节点是否为空,为空直接返回就不需要再往下递归了,不为空就往上下左右四个方向找下一个字符...

cpp 复制代码
class Solution
{
public:
    struct Node
    {
        Node *son[26] = {0};
        string w;
    };
    Node *root = new Node;

    int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
    int n, m;
    vector<vector<char>> _board;
    vector<string> ret;
    void dfs(Node *cur, int i, int j)
    {
        Node *tmp = cur->son[_board[i][j] - 'a'];
        if (tmp == nullptr)
        {
            return;
        }
        if (!tmp->w.empty())
        {
            ret.push_back(tmp->w);
            tmp->w = ""; // 剪枝
            // return; 可能存在app apple
        }
        // 在这里进行标记
        char ch = _board[i][j];
        _board[i][j] = '#';
        for (int k = 0; k < 4; k++)
        {
            int x = dx[k] + i, y = dy[k] + j;
            if (x >= 0 && x < n && y >= 0 && y < m && _board[x][y] != '#' && tmp->son[_board[x][y] - 'a'] != nullptr)
            {
                dfs(tmp, x, y);
            }
        }
        // 递归结束这里进行复原
        _board[i][j] = ch;
    }
    void CreateNode(const string &s)
    {
        Node *tmp = root;
        for (int i = 0; i < s.size(); i++)
        {
            int pos = s[i] - 'a';
            if (tmp->son[pos] == nullptr)
            {
                tmp->son[pos] = new Node;
            }
            tmp = tmp->son[pos];
        }
        tmp->w = s;
    }
    vector<string> findWords(vector<vector<char>> &board, vector<string> &words)
    {
        n = board.size(), m = board[0].size();
        _board = board;
        for (auto &word : words)
        {
            CreateNode(word);
        }
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                dfs(root, i, j);
            }
        }
        return ret;
    }
};

电话号码的自由组合

解法:递归暴搜

cpp 复制代码
class Solution
{
public:
    string hash[10] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    vector<string> ret;
    string path, _digits;
    void dfs(int pos)
    {
        if (path.size() == _digits.size())
        {
            ret.push_back(path);
            return;
        }
        string s = hash[_digits[pos] - '0'];
        for (int i = 0; i < s.size(); i++)
        {
            path += s[i];
            dfs(pos + 1);
            path.pop_back();
        }
    }
    vector<string> letterCombinations(string digits)
    {
        _digits = digits;
        dfs(0);
        return ret;
    }
};

组合

解法:递归

从当前位置开始往后递归收集组合

cpp 复制代码
class Solution
{
public:
    vector<vector<int>> ret;
    vector<int> path;
    int _n, _k;
    void dfs(int pos)
    {
        if (path.size() == _k)
        {
            ret.push_back(path);
            return;
        }
        for (int i = pos; i <= _n; i++)
        {
            path.push_back(i);
            // i往后递归,就不会出现数字重复出现在path中
            dfs(i + 1);
            path.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k)
    {
        _n = n;
        _k = k;
        dfs(1);
        return ret;
    }
};

全排列

解法:递归

递归暴搜,但要当前位置收集后要进行标记,防止重复递归收集

cpp 复制代码
class Solution
{
public:
    vector<vector<int>> ret;
    vector<int> path, _nums;
    bool vis[7] = {false};
    int n;
    void dfs()
    {
        if (path.size() == n)
        {
            ret.push_back(path);
            return;
        }
        for (int i = 0; i < n; i++)
        {
            if (!vis[i])
            {
                // 标记位置,相同位置不能递归
                vis[i] = true;
                path.push_back(_nums[i]);
                dfs();
                vis[i] = false;
                path.pop_back();
            }
        }
    }
    vector<vector<int>> permute(vector<int> &nums)
    {
        n = nums.size();
        _nums = nums;
        dfs();
        return ret;
    }
};

全排列二

解法:递归

特殊判断:除了当前位置标记后不能递归外,还有 nums[i] == nums[i-1] 且 i-1 位置被标记过,这种情况也是不能递归的

cpp 复制代码
class Solution
{
public:
    vector<vector<int>> ret;
    vector<int> path;
    bool vis[9] = {false};
    int n;
    void dfs(const vector<int> &_nums)
    {
        if (path.size() == n)
        {
            ret.push_back(path);
            return;
        }
        for (int i = 0; i < n; i++)
        {
            if (vis[i] || (i - 1 >= 0 && _nums[i] == _nums[i - 1] && vis[i - 1]))
            {
                continue;
            }
            // 标记位置,相同位置不能递归
            vis[i] = true;
            path.push_back(_nums[i]);
            dfs(_nums);
            vis[i] = false;
            path.pop_back();
        }
    }
    vector<vector<int>> permuteUnique(vector<int> &nums)
    {
        n = nums.size();
        sort(nums.begin(), nums.end());
        dfs(nums);
        return ret;
    }
};

组合总和

思路1

收集到的组合先排序,在放到set进行去重,得到的答案才正确

思路2

先排序,从当前位置往后开始递归,就不需要去重和在加入ret时排序了

cpp 复制代码
class Solution
{
public:
    set<vector<int>> ret;
    vector<int> path;
    int n;
    void dfs(vector<int> &candidates, int target)
    {
        if (target <= 0)
        {
            if (target == 0)
            {
                // 直接排序恢复现场的逻辑就错了
                vector<int> _path = path;
                sort(_path.begin(), _path.end());
                ret.insert(_path);
            }
            return;
        }
        for (int i = 0; i < n; i++)
        {
            path.push_back(candidates[i]);
            dfs(candidates, target - candidates[i]);
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum(vector<int> &candidates, int target)
    {
        n = candidates.size();
        dfs(candidates, target);
        vector<vector<int>> ans(ret.begin(), ret.end());
        return ans;
    }
};
// 先排序,从当前位置往后开始递归,就不需要去重和在加入ret时排序了
class Solution
{
public:
    vector<vector<int>> ret;
    vector<int> path;
    int sum = 0;
    void dfs(vector<int> &candidates, int target, int pos)
    {
        if (sum >= target || pos == candidates.size())
        {
            if (sum == target)
                ret.push_back(path);
            return;
        }
        for (int i = pos; i < candidates.size(); i++)
        {
            path.push_back(candidates[i]);
            sum += candidates[i];
            dfs(candidates, target, i);
            sum -= candidates[i];
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum(vector<int> &candidates, int target)
    {
        sort(candidates.begin(), candidates.end());
        dfs(candidates, target, 0);
        return ret;
    }
};

N皇后二

与N皇后思路一致,也是要解决坐标之间怎么判断在同一个正副斜线上

cpp 复制代码
class Solution
{
public:
    int ret;
    vector<string> path;
    int _n;
    bool col[9] = {false}, slash[81] = {false}, subtline[81] = {false};
    void dfs(int i)
    {
        if (i == _n)
        {
            ret++;
            return;
        }
        for (int j = 0; j < _n; j++)
        {
            // if(path[i][j] == '.' && !col[j] && !slash[j + i] && !subtline[j - i])
            if (!col[j] && !slash[j + i] && !subtline[j - i])
            {
                path[i][j] = 'Q';
                col[j] = slash[j + i] = subtline[j - i] = true;
                dfs(i + 1);
                path[i][j] = '.';
                col[j] = slash[j + i] = subtline[j - i] = false;
            }
        }
    }
    int totalNQueens(int n)
    {
        _n = n;
        for (int i = 0; i < n; i++)
        {
            path.emplace_back(n, '.');
        }
        dfs(0);
        return ret;
    }
};

括号生成

解法:dfs

思考:什么情况下括号不需要再往下递归了?

当左括号 < 右括号,左括号 > n,右括号 > n 这三种情况下一定不能收集到正确的括号匹配

cpp 复制代码
class Solution
{
public:
    vector<string> ret;
    string path;
    int left = 0, right = 0, _n;
    void dfs()
    {
        if (left < right || left > _n || right > _n)
        {
            return;
        }
        if (left == _n && right == _n)
        {
            ret.push_back(path);
            return;
        }
        left++;
        path += '(';
        dfs();
        left--;
        path.pop_back();

        right++;
        path += ')';
        dfs();
        right--;
        path.pop_back();
    }
    vector<string> generateParenthesis(int n)
    {
        _n = n;
        dfs();
        return ret;
    }
};

单词搜索

解法:dfs

cpp 复制代码
class Solution
{
public:
    int n, m;
    bool vis[6][6] = {false};
    int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
    bool dfs(vector<vector<char>> &board, const string &word, int i, int j, int pos)
    {
        if (pos == word.size())
        {
            return true;
        }
        for (int k = 0; k < 4; k++)
        {
            int x = dx[k] + i, y = dy[k] + j;
            if (x >= 0 && x < n && y >= 0 && y < m && board[x][y] == word[pos] && !vis[x][y])
            {
                vis[x][y] = true;
                if (dfs(board, word, x, y, pos + 1))
                {
                    return true;
                }
                vis[x][y] = false;
            }
        }
        return false;
    }
    bool exist(vector<vector<char>> &board, string word)
    {
        n = board.size(), m = board[0].size();
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (word[0] == board[i][j])
                {
                    vis[i][j] = true;
                    if (dfs(board, word, i, j, 1))
                    {
                        return true;
                    }
                    vis[i][j] = false;
                }
            }
        }
        return false;
    }
};

以上便是全部内容,有问题欢迎在评论区指正,感谢观看!

相关推荐
零雲1 小时前
java面试:有了解过springboot的自动装配流程吗?
java·spring boot·面试
请叫我大虾1 小时前
数据结构与算法-分裂问题,将数字分成0或1,求l到r之间有多少个1.
java·算法·r语言
hetao17338371 小时前
2026-03-04~03-06 hetao1733837 的刷题记录
c++·算法
逆境不可逃2 小时前
【从零入门23种设计模式16】行为型之迭代器模式
java·开发语言·数据结构·算法·设计模式·职场和发展·迭代器模式
xiaoye-duck2 小时前
《算法题讲解指南:优选算法-分治-归并》--47.归并排序,48.数组中的逆序对
c++·算法
Darkwanderor2 小时前
图论——最短路问题
c++·算法·图论·最短路
Java练习两年半2 小时前
互联网大厂 Java 求职面试:探讨微服务与云原生
java·微服务·云原生·面试·技术栈
Filotimo_2 小时前
3.4 图
算法·图论
I_LPL2 小时前
day49 代码随想录算法训练营 图论专题2
java·算法·深度优先·图论·广度优先·求职面试