力扣leetcode-算法基础21天刷题记录②


力扣【leetcode】 算法基础21天刷题 记录篇二

打题啊打题,打题啊打题,坚持!!!


⭐广度优先搜索 / 深度优先搜索


200. 岛屿数量


给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。


深搜DFS


一个点,再向四周进行遍历搜索


class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int sum = 0;
        // 对岛屿每个点进行遍历
        for(int i = 0; i < grid.size(); ++i){
            for (int j = 0; j < grid[0].size(); ++j){
                if (grid[i][j] == '1') {
                    ++sum;
                    dfs(grid, i, j);
                }
            }
        }
        return sum;
    }

     void dfs(vector<vector<char>>& grid, int x, int y){
        // 岛屿触碰边界以及本身是水即返回
        if(x < 0 || x >= grid.size() || y < 0 || y >=grid[0].size() || grid[x][y] == '0') {
            return;
        }
        // 将自身变成水
        grid[x][y] = '0';
        // 下上右左
        int ix[4] = {0, 0, 1, -1};
        int iy[4] = {1, -1, 0, 0};

        for(int i = 0; i < 4; ++i){
            int xx = x + ix[i], yy = y + iy[i];
            // 继续往四周探寻
            dfs(grid, xx, yy);
        }
       	return;
    }
};

广搜BFS


一个点的四周加入队列,进行循环pop首部节点


class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int sum = 0;
        // 对岛屿每个点进行遍历
        for(int i = 0; i < grid.size(); ++i){
            for (int j = 0; j < grid[0].size(); ++j){
                if (grid[i][j] == '1') {
                    ++sum;
                    bfs(grid, i, j);
                }
            }
        }
        return sum;
    }

     void bfs(vector<vector<char>>& grid, int x, int y){
         if (x < 0 || y < 0 || x >= grid.size() || y >= grid[0].size() || grid[x][y] == '0')
            return;
         // 创建队列
         grid[x][y] = '0';
         queue<pair<int, int>> q;
         int ix[4] = {0, 0, 1, -1};
         int iy[4] = {1, -1, 0, 0};
         // 将该点作为首部节点传入队列
         q.emplace(x, y);
         // 进行循环pop队列首节点
         while(!q.empty()){
             // 取出首部节点,对其进行条件判断
             int x = q.front().first;
             int y = q.front().second;
             // 满足是岛屿,则将该节点pop且将四周节点加入到队列
             q.pop();
             for(int i = 0; i < 4; ++i) {
                 int xx = x + ix[i], yy = y + iy[i];
                 if (xx >= 0 && xx < grid.size() && yy >= 0 && yy < grid[0].size() && grid[xx][yy] == '1') {
                     // 将搜索过的岛屿置0
                     grid[xx][yy] = '0';
                     q.emplace(xx,yy);
                 }
             }
         }
         return;
     }
};

547. 省份数量


有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。


DFS


class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        int sum = 0;
        // 初始化0 记录该点是否遍历过
        vector<int> visited(isConnected.size(),0);
        for(int i = 0; i < isConnected.size(); ++i) {
            if(!visited[i]) {
                dfs(isConnected, visited, i);
                ++sum;
            }
        }
        return sum;
    }
    
    // 以下两者皆可
    
    // void dfs(vector<vector<int>>& isConnected, vector<int>& visited, int x){
    //     // 标记已经遍历过
    //     visited[x] = 1;
    //     for(int i = 0; i < isConnected[0].size(); ++i) {
    //         // 如果未探寻过并且存在连接则继续探寻
    //         if(isConnected[x][i] == 1 && !visited[i]) {
    //             dfs(isConnected, visited, i);
    //         }   
    //     }
    // }
    void dfs(vector<vector<int>>& isConnected, vector<int>& visited, int x){
        for(int i = 0; i < isConnected.size(); ++i) {
            // 如果未探寻过并且存在连接则继续探寻
            if(isConnected[x][i] == 1 && !visited[i]) {
                // 标记已经遍历过
                visited[i] = 1;
                dfs(isConnected, visited, i);
            }   
        }
    }
};

BFS


class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        int sum = 0;
        // 初始化0 记录该点是否遍历过
        vector<int> visited(isConnected.size(),0);
        for(int i = 0; i < isConnected.size(); ++i) {
            if(!visited[i]) {
                bfs(isConnected, visited, i);
                ++sum;
            }
        }
        return sum;
    }
    void bfs(vector<vector<int>>& isConnected, vector<int>& visited, int k){
        queue<int> q;
        q.push(k);
        while(!q.empty()) {
            int x = q.front();
            q.pop();
            visited[x] = 1;
            for(int i = 0; i < isConnected.size(); ++i){
                if(!visited[i] && isConnected[x][i] == 1) {
                    q.push(i);
                }
            }
        }
        
    }
};

117. 填充每个节点的下一个右侧节点指针 II


给定一个二叉树


struct Node {
int val;
Node *left;
Node *right;
Node *next;
}

它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。

初始状态下,所有 next 指针都被设置为 NULL。

进阶:

你只能使用常量级额外空间。
使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。


BFS


/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        if(!root){
            return nullptr;
        }
        queue<Node*> q;
        q.push(root);
        while(!q.empty()){
            int n = q.size();
            Node* p = nullptr;
            for(int i = 0; i < n; ++i){
                Node* m = q.front();
                q.pop();
                if(m->left){
                    q.push(m->left);
                }
                if(m->right){
                    q.push(m->right);
                }
                if(i!=0){
                    p->next = m;
                }
                p = m;
            }
        }
        return root;
    }
};

层序遍历模板


class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        if (!root){
            return nullptr;
        }
        queue<Node*> q;
        q.push(root);
        vector<vector<int>> result;
        while (!q.empty()) {
            int n = q.size();
            vector<int> p;
            for (int i = 0; i < n; i++) {
                Node* node = q.front();
                q.pop();
                p.push_back(node->val);
                if (node->left) {
                    q.push(node->left);
                }
                if (node->right) {
                    q.push(node->right);
                }
            }
            result.push_back(p);
        }
        return result;
    }
};

572. 另一棵树的子树


给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
     bool isSame(TreeNode*root,TreeNode*subRoot)
    {
        if(!root && !subRoot) {
            return true;
        }
        if(!root||!subRoot) {
            return false;
        }
        if(root->val != subRoot->val){
            return false;
        }   
        // 若为同个树,则移动左右指针
        return isSame(root->left,subRoot->left) && isSame(root->right,subRoot->right);
    }
    bool isSubtree(TreeNode* root, TreeNode* subRoot) {
        if(!subRoot){
            return true;
        }
        if(!root) {
            return false;
        }
        // 树相同 为左子树 为右子树
        return isSame(root,subRoot) || isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
    }
};

1091. 二进制矩阵中的最短路径


给你一个 n x n 的二进制矩阵 grid 中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回 -1 。

二进制矩阵中的 畅通路径 是一条从 左上角 单元格(即,(0, 0))到 右下角 单元格(即,(n - 1, n - 1))的路径,该路径同时满足下述要求:

路径途经的所有单元格都的值都是 0 。
路径中所有相邻的单元格应当在 8 个方向之一 上连通(即,相邻两单元之间彼此不同且共享一条边或者一个角)。
畅通路径的长度 是该路径途经的单元格总数。


// 该题求解最短路径,自然而可以考虑 BFS
class Solution {
public:
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        // 起点就不符合条件
        if(grid[0][0] != 0) {
            return -1;
        }
       // 生成队列,首部节点
        queue<pair<int, int>> q;
        q.emplace(0, 0);
        // 标记
        grid[0][0] = 1;
        // 记录路径数
        int sum = 0; 
        // 方向数组
        int dirX[8] = {0, 0, 1, -1, 1, 1, -1, -1};
        int dirY[8] = {1, -1, 0, 0, 1, -1, -1, 1};
        // 进行循环队列首部节点判断
        while(!q.empty()) {
            ++sum;
            for (int i = q.size(); i > 0; --i) {
                 // 取出首部节点
                int x = q.front().first;
                int y = q.front().second;
                q.pop();

                // 到达目的地
                if (x == grid.size() - 1 && y == grid[0].size() - 1) {
                    return sum;
                }

                // 对八个方向进行遍历
                for(int i = 0; i < 8; ++i) {
                    int xx = x + dirX[i], yy = y + dirY[i];
                    // 若满足在矩阵内且通路
                    if (xx >= 0 && xx < grid.size() && yy >= 0 && yy < grid[0].size() && grid[xx][yy] == 0) {
                        // 标记
                        grid[xx][yy] = 1;
                        // 加入队列
                        q.emplace(xx, yy);
                    }
                }
            }           
        }
        return -1;
    }
};

130. 被围绕的区域


给你一个 m x n 的矩阵 board ,由若干字符 'X''O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O''X' 填充。


DFS


// 找出边界上的和O的连通点
class Solution {
public:
    void solve(vector<vector<char>>& board) {
        if (board.size() == 0) {
            return;
        }
        // 深搜第一层和最后一层
        for (int i = 0; i < board.size(); ++i) {
            dfs(board, i, 0);
            dfs(board, i, board[0].size() - 1);
        }

        // 深搜第一列和最后一列
        for (int i = 1; i < board[0].size() - 1; ++i) {
            dfs(board, 0, i);
            dfs(board, board.size() - 1, i);
        }


        for(int i = 0; i < board.size(); ++i) {
            for(int j = 0; j < board[0].size(); ++j) {
                // 若被标记,则该点无法变成X
                if(board[i][j] == 'P') {
                    board[i][j] = 'O';
                }
                // 满足条件,将O变为X
                else if (board[i][j] == 'O') {
                    board[i][j] = 'X';
                }
            }
        }
    }
    void dfs(vector<vector<char>>& board, int x, int y) {
        // 边界,无需变X 的条件
        if (x < 0 || x >= board.size() || y < 0 || y >= board[0].size() || board[x][y] != 'O') {
            return ;
        }
        // 标记边界上的可通点,即边界上无法变X
        board[x][y] = 'P';
        // 向四周进行搜索
        int ix[4] = {0, 0, 1, -1};
        int iy[4] = {1, -1, 0, 0};
        for(int i = 0; i < 4; ++i) {
            int xx = x + ix[i], yy = y + iy[i];
            dfs(board, xx, yy);
        }
        return;
    }
};

BFS


// 找出边界上的和O的连通点
class Solution {
public:
    void solve(vector<vector<char>>& board) {
        if (board.size() == 0) {
            return;
        }
        // 深搜第一层和最后一层
        for (int i = 0; i < board.size(); ++i) {
            bfs(board, i, 0);
            bfs(board, i, board[0].size() - 1);
        }

        // 深搜第一列和最后一列
        for (int i = 1; i < board[0].size() - 1; ++i) {
            bfs(board, 0, i);
            bfs(board, board.size() - 1, i);
        }


        for(int i = 0; i < board.size(); ++i) {
            for(int j = 0; j < board[0].size(); ++j) {
                // 若被标记,则该点无法变成X
                if(board[i][j] == 'P') {
                    board[i][j] = 'O';
                }
                // 满足条件,将O变为X
                else if (board[i][j] == 'O') {
                    board[i][j] = 'X';
                }
            }
        }
    }
    void bfs(vector<vector<char>>& board, int x, int y) {
        // 边界,无需变X 的条件
        if (x < 0 || x >= board.size() || y < 0 || y >= board[0].size() || board[x][y] != 'O') {
            return ;
        }
        // 标记边界上的可通点,即边界上无法变X
        board[x][y] = 'P';

        queue<pair<int, int>> q;
        q.emplace(x, y);
        // 向四周进行搜索
        int ix[4] = {0, 0, 1, -1};
        int iy[4] = {1, -1, 0, 0};

        while(! q.empty()) {
            int x = q.front().first;
            int y = q.front().second;
            q.pop();
            for(int i = 0; i < 4; ++i) {
                int xx = x + ix[i], yy = y + iy[i];
                bfs(board, xx, yy);
            }
        }     
        return;
    }
};

797. 所有可能的路径


给一个有 n 个结点的有向无环图,找到所有从 0 到 n-1 的路径并输出(不要求按顺序)

二维数组的第 i 个数组中的单元都表示有向图中 i 号结点所能到达的下一些结点(译者注:有向图是有方向的,即规定了 a→b 你就不能从 b→a )空就是没有下一个结点了。


class Solution {
public:
    vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
        vector<vector<int>> sum;
        vector<int> n = {0};
        dfs(sum, graph, n);
        return sum;
    }

    void dfs(vector<vector<int>> &sum, vector<vector<int>> &graph, vector<int> &n) {
        for(auto &p: graph[n.back()]) {
            n.push_back(p);
            if (p == graph.size() - 1) {
                sum.push_back(n);
            }
            else {
                dfs(sum, graph, n);
            }
            n.pop_back();
        }
    }
};

⭐递归 / 回溯


迭代回溯


从根节点进行搜索 =》 如果当前节点存在子节点,否则不存在子节点,返回上一层 =》遍历当前节点的所有子节点 =》 若满足约束条件和限界条件则得到一个可行解,否则继续向下搜索。


78. 子集


给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。


class Solution {
public:
    // 记录当前路径,便于回溯
    vector<int> path;
    // 返回结果集
    vector<vector<int>> result;

    vector<vector<int>> subsets(vector<int>& nums) {
        backtracking(nums, 0);
        return result;
    }

    // 进行回溯
    void backtracking(vector<int>& nums, int start) {
        // 结束条件,当start指向最后
        if (start == nums.size()) {
            // 搜寻结束,加入结果集
            result.push_back(path);
            return;
        }
        // 将该选择加入路径队列中
        path.push_back(nums[start]);
        // 进行回溯
        backtracking(nums, start + 1);
        // 回退一格
        path.pop_back();
        backtracking(nums,start + 1);
    }
};

90. 子集 II


给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。


// 与上一题不同点是,可能存在重复元素
class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        // 先对其进行排序
        sort(nums.begin(), nums.end());
        // 回溯
        backtracking(nums, 0);
        return result;
    }

    void backtracking(vector<int>& nums, int start) {
        // 将path加入结果集
        result.push_back(path);
        // 结束条件
        if (nums.size() == start) {   
            return;
        }
        // 遍历该结点以下的结点
        for (int i = start; i < nums.size(); ++i) {
            // 防止因重复元素出现重复子集
            if (i > start && nums[i] == nums [i-1]) continue;
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }       
    }
};

47. 全排列 II


给定一个可包含重复数字的序列 nums按任意顺序 返回所有不重复的全排列。


class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;

    vector<vector<int>> permuteUnique(vector<int>& nums) {
        // 排序,为剪枝做准备
        sort(nums.begin(), nums.end());
        // 申请一个数组,来标记是否已经经过,初始化为0
        vector<int> visited(nums.size(), 0);
        backtracking(nums, visited);
        return result;
    }

    void backtracking(vector<int>& nums, vector<int> visited) {
        // 此题为全排列,即路径长度等于nums元素总个数
        if (path.size() == nums.size()) {
            result.push_back(path);
            return;
        }
        for (int i = 0; i < nums.size(); ++i) {
            // 跟之前的去重不同,此时是同层去重
            if (i != 0 && nums[i] == nums[i-1] && visited[i-1] == 0) continue;
            // 元素未被使用
            if (visited[i] == 0) {
                // 加入路径
                path.push_back(nums[i]);
                // 标记元素被访问
                visited[i] = 1;
                backtracking(nums, visited);
                // 回溯上一个元素
                path.pop_back();
                // 此时标记该元素为未访问
                visited[i] = 0;
            }
        }
    }
};

39. 组合总和


给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。

candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。

对于给定的输入,保证和为 target 的唯一组合数少于 150 个


class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        // 调用回溯
        backtracking(candidates, target, 0);
        return result;
    }

    void backtracking(vector<int>& candidates, int target, int start) {
        // 结束条件,元素利用完了
        if (start == candidates.size()) return;
        // 此时和等于给定数,则加入结果集
        if (target == 0) {
            result.push_back(path);
            return;
        }
        // 开始寻找
        if (target - candidates[start] >= 0) {
            path.push_back(candidates[start]);
            // 注意这里的起始点还是i,因为元素可以重复使用
            backtracking(candidates, target - candidates[start], start);
            path.pop_back();
        }
        // 跳过继续搜寻
        backtracking(candidates, target, start + 1);
    }

};

40. 组合总和 II


给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

注意:解集不能包含重复的组合。


// 与上题不同,数字、结果均不能重复
class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;

    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        // 剪枝必备
        sort(candidates.begin(), candidates.end());
        backtracking(candidates, target, 0);
        return result;
    }

    void backtracking(vector<int>& candidates, int target, int start) {
        // 结束条件
        if (target == 0) {
            // 符合条件加入结果集
            result.push_back(path);
            return;
        }
        // 往下遍历结点
        for (int i = start; i < candidates.size(); ++i) {
            // 去重
            if (i > start && candidates[i] == candidates[i - 1]) continue;
            // 给定求和条件
             if (target - candidates[i] >= 0) {
                path.push_back(candidates[i]);
                // 这题是i+1,因为每个数字不可重复使用
                backtracking(candidates, target-candidates[i], i + 1);
                path.pop_back();
            }
        }
    }
};

17. 电话号码的字母组合


给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。


// 题目本质就是组合,可先用哈希表映射字符和数字的对应关系,然后继续回溯

class Solution {
public:
    vector<string> result;
    string path;

    vector<string> letterCombinations(string digits) {
        // 当输入的字符串为空,直接返回
        if (digits == "") return result;
        // 数字和字母的映射,存至哈希表
        unordered_map<char, string> phoneMap{
            {'2', "abc"},
            {'3', "def"},
            {'4', "ghi"},
            {'5', "jkl"},
            {'6', "mno"},
            {'7', "pqrs"},
            {'8', "tuv"},
            {'9', "wxyz"}
        };
        backtracking(digits, phoneMap, 0);
        return result;
    }

    // 回溯函数
    void backtracking(string digits, const unordered_map<char, string>& phoneMap, int start) {
        // 结束条件
        if (start == digits.size()) {
            result.push_back(path);
        }
        else {
            // 根据哈希表获取输入数字对应的字母,指向second,是因为字母字符串在第二个位置
            auto str = phoneMap.find(digits[start])->second;
            for (auto s: str) {
                // 将单个字符作为一个结点,进行回溯组合
                path.push_back(s);
                backtracking(digits, phoneMap, start + 1);
                path.pop_back();
            }
        }

    }
};

22. 括号生成


数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

有效括号组合需满足:左括号必须以正确的顺序闭合。


class Solution {
public:
    vector<string> result;
    string path;
    vector<string> generateParenthesis(int n) {
        // n左右,一半就行
        backtracking(n * 2);
        return result;
    }

    void backtracking(int n) {
        // 结束条件
        if (n == path.size()) {
            // 检验path左右括号是否合法
            if (isCheck(path)) {
                result.push_back(path);
            }
            return;
        }
        // 进行回溯
        // 左括号
        path.push_back('(');
        backtracking(n);
        path.pop_back();
        // 右括号
        path.push_back(')');
        backtracking(n);
        path.pop_back();
    }

    bool isCheck(string path) {
        // 记录左括号和右括号的平衡度
        int ans = 0;
        for (auto s : path) {
            if (s == '(') {
                ++ans;
            }
            else {
                --ans;
            }
            // 此时不平衡
            if (ans < 0) {
                return false;
            }
        }
        // 平衡则返回true
        return ans == 0;
    }
};

79. 单词搜索


给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

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


class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        vector<vector<int>> visited(board.size(), vector<int>(board[0].size()));
        for(int i = 0; i < board.size(); ++i) {
            for (int j = 0; j < board[0].size(); ++j) {
                if (dfs(board, word, visited, i , j, 0)) {
                    return true;
                }
            }
        }
        return false;
    }

    // visited 数组
    bool dfs(vector<vector<char>>& board, string word, vector<vector<int>>& visited, int x, int y, int start) {
        // 当前位置不存在或访问使用过
        if (x < 0 || x > board.size() || y < 0 || y > board[0].size() || visited[x][y] == 1) {
            return false;
        }
        // 不符合条件
        if (board[x][y] != word[start]) {
            return false;
        }
        // 搜寻完毕
        if (start == word.size() - 1) {
            return true;
        }
        // 定义四周方向
        int dirX[4] = {0, 0, 1, -1};
        int dirY[4] = {1, -1, 0, 0};
        // 标记
        visited[x][y] = 1;
        // 四周探寻
        for (int i = 0; i < 4; ++i) {
            int xx = x + dirX[i], yy = y + dirY[i];
            if (xx >= 0 && xx < board.size() && yy >= 0 && yy < board[0].size() && visited[xx][yy] == 0) {
                if (dfs(board, word, visited, xx, yy, start + 1)) {
                    return true;
                }
            }
        }
        // 回退
        visited[x][y] = 0;
        return false;
    }
};

posted @ 2021-08-16 15:09  J1ay  阅读(146)  评论(0编辑  收藏  举报