LeetCode刷题之BFS算法

LeetCode刷题之BFS算法

1.基本思路及代码框架

BFS算法起源于二叉树的层序遍历,其核心是利用队列这种数据结构。

BFS的核心思想就是把一些问题抽象成图,从一个点开始,向四周扩散。一般来说,我们写BFS算法都是用到队列这种数据结构,每次将一个节点周围的所有节点加入队列。

BFS和DFS最主要的区别就是:BFS找到的路径一定是最短的,但代价就是空间复杂度可能比DFS大很多。

BFS出现的常见情景,就是:问题的本质就是让你在一幅图中找到从起点start到终点target的最近距离,这个例子听起来很枯燥,但是BFS算法问题其实都是在干这个事。基本代码框架如下:

int BFS(Node *start, Mode *target) {
    queue<Node*> q; //BFS的核心数据结构队列
    set<Node*> visited; //避免走回头路
    
    q.push(start); //将起点加入队列
    visited.insert(start); 
    int step = 0; //往下扩散的步数
    
    while (!q.empty()) {
        int sz = q.size();
        for (int i = 0; i < sz; i++) { //将当前节点往四周进行扩散
            Node *cur = q.front();
            if (cur == target) { //判断是否到达终点
                return;
            }
            for (auto x : cur.adj) { //将cur相邻的节点加入队列
                if (!visited.count(x)) {
                    q.push(x);h
                    visited.insert(x);
                }
            }
        }
         step++;//更新步数
    }  
}

2.题目解答

1.LeetCode之111二叉树的最小深度

  • 解题思路

    使用广度优先遍历求解,每次向前走一步寻找最小的距离。

  • 代码实现

    /*
     * @lc app=leetcode.cn id=111 lang=cpp
     *
     * [111] 二叉树的最小深度
     */
    
    // @lc code=start
    /**
     * 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:
        int minDepth(TreeNode* root) {
            if (root == nullptr) {
                return 0;
            }
            queue<TreeNode*> q;
            q.push(root);
            int depth = 1;
            while (!q.empty()) {
                int sz = q.size();
                for (int i = 0; i < sz; i++) {
                    TreeNode *node = q.front();
                    q.pop();
                    if (node->left == nullptr && node->right == nullptr) {
                        return depth;
                    }
                    if (node->left != nullptr) {
                        q.push(node->left);
                    }
                    if (node->right != nullptr) {
                        q.push(node->right);
                    }
                }
                depth++;
            }
            return depth;
        }
    };
    // @lc code=end
    

2.LeetCode之752打开转盘锁

  • 解题思路

    可以将此问题抽象成一个图问题,然后采用广度优先遍历进行解决,每一个节点有八个邻节点。

  • 代码实现

    1.使用单向BFS

    /*
     * @lc app=leetcode.cn id=752 lang=cpp
     *
     * [752] 打开转盘锁
     */
    
    // @lc code=start
    class Solution {
    public:
        int openLock(vector<string>& deadends, string target) {
            queue<string> q;
            set<string> visited;
            set<string> dead;
            for (auto h : deadends) {
                dead.insert(h);
            }
            string s("0000");
            q.push(s);
            visited.insert(s);
            int step = 0;
            while (!q.empty()) {
                int sz = q.size();
                for (int i = 0; i < sz; i++) {
                    string m = q.front();
                    q.pop();
                    if (dead.count(m) == 1) {
                        continue;
                    }
                    if (m == target) {
                        return step;
                    }
                    for (int j = 0; j < 4; j++) {
                        string up = plusOne(m, j);
                        string down = minuOne(m, j);
                        if (visited.count(up) == 0) {
                            q.push(up);
                            visited.insert(up);
                        }
                        if (visited.count(down) == 0) {
                            q.push(down);
                            visited.insert(down);
                        }
                    }
                }
                step++;
            }
            return -1;
        }
    
        string plusOne(string s, int i) { //将字符串的某一位加一
            if (s[i] == '9') {
                s[i] = '0';
            } else {
                s[i] = s[i] + 1;
            }
            return string(s);
        }
    
        string minuOne(string s, int i) {
            if (s[i] == '0') {
                s[i] = '9';
            } else {
                s[i] -= 1;
            }
            return string(s);
        }
    };
    // @lc code=end
    

    2.使用双向BFS进行优化

    /*
     * @lc app=leetcode.cn id=752 lang=cpp
     *
     * [752] 打开转盘锁
     */
    
    // @lc code=start
    class Solution {
    public:
        int openLock(vector<string>& deadends, string target) {
            set<string> dead;
            for (auto str : deadends) {
                dead.insert(str);
            }
            set<string> q1;
            set<string> q2;
            set<string> visited;
    
            int step = 0;
            q1.insert(string("0000"));
            q2.insert(target);
    
            while(!q1.empty() && !q2.empty()) {
                set<string> temp;
    
                for (auto cur : q1) {
                    if (dead.count(cur)) {
                        continue;
                    }
                    if (q2.count(cur)) {
                        return step;
                    }
                    visited.insert(cur);
                    for (int j = 0; j < 4; j++) {
                        string up = plusOne(cur, j);
                        string down = minuOne(cur, j);
                        if (visited.count(up) == 0) {
                            temp.insert(up);
                        }
                        if (visited.count(down) == 0) {
                            temp.insert(down);
                        }
                    }
                }
                step++;
                q1 = q2;
                q2 = temp;
            }
            return -1;
        }
    
        string plusOne(string s, int i) { //将字符串的某一位加一
            if (s[i] == '9') {
                s[i] = '0';
            } else {
                s[i] = s[i] + 1;
            }
            return string(s);
        }
    
        string minuOne(string s, int i) {
            if (s[i] == '0') {
                s[i] = '9';
            } else {
                s[i] -= 1;
            }
            return string(s);
        }
    };
    // @lc code=end
    

3.LeetCode之773滑动谜题

  • 解题思路

    利用BFS进行暴力穷举,将问题抽象成一个图问题。

  • 代码实现

    /*
     * @lc app=leetcode.cn id=773 lang=cpp
     *
     * [773] 滑动谜题
     */
    
    // @lc code=start
    class Solution {
    public:
        int slidingPuzzle(vector<vector<int>>& board) {
            int m =2, n = 3;
            string target = "123450"; //将二维数组转化成一维数组
            string start = "";
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    start.push_back(board[i][j] + '0');
                }
            }
    
            //记录一维数组的相邻索引
            vector<vector<int>> neighbor = {
                {1, 3},
                {0, 4, 2},
                {1, 5},
                {0, 4},
                {3, 1, 5},
                {4, 2}
            };
    
            //BFS算法开始
            queue<string> q;
            set<string> visited;
            int step = 0;
            q.push(start);
            visited.insert(start);
    
            while(!q.empty()) {
                int sz = q.size();
                for (int i = 0; i < sz; i++) {
                    string cur = q.front();
                    q.pop();
                    if (cur == target) {
                        return step;
                    }
                    int idx = 0;
                    for(; cur[idx] != '0'; idx++);
                    for (auto adj : neighbor[idx]) {
                        string new_board = cur;
                        swap(new_board[idx], new_board[adj]);
                        if (visited.count(new_board) == 0) {
                            q.push(new_board);
                            visited.insert(new_board);
                        }
                    }
                }
                step++;
            }
            return -1;
        }
    };
    // @lc code=end
    
posted @ 2021-11-25 13:18  IU_UI  阅读(186)  评论(0编辑  收藏  举报